! CIF VIEW J. Gordon Hughes May 1984 {#######################################################################} {# #} {# This program is part of the ILAP library, and was written in #} {# The Department of Computer Science at the University of Edinburgh #} {# (James Clerk Maxwell Building, Kings Buildings, Edinburgh) #} {# #} {# This software is available free to other educational establisments #} {# but the University of Edinburgh, retains all commercial rights. #} {# It is a condition of having this software is that the sources are #} {# not passed on to any other site, and that Edinburgh University is #} {# given credit in any re-implementations of any of the algorithms #} {# used, or articles published which refer to the software. #} {# #} {# There is no formal support for this software, but any bugs should #} {# be reported to Gordon Hughes or David Rees at the above address, #} {# and these are likely to be fixed in a future release. #} {# #} {#######################################################################} %const %integer TRUE=1, FALSE = 0 %record %format POINTFM (%integer X, Y) ! The routine interface to CIFSYS - %external %string (31) %fn %spec CIFSYS VERSION %external %routine %spec ANAL OR DRAW CIF (%integer PARM, CELL, MAX LAYERS, FACTOR, %string (4) %array %name LAYER NAMES(1:15), %integer %array %name VALID(1:15), %integer %array %name PERCENTAGES(1:15)) %external %routine %spec LIST CELLS (%integer ILAP SCALE, INTERACTS, NUM ON PAGE) %external %integer %fn %spec FIND CELL (%string (255) NAME, %integer N, %integer %name XL, YB, XR, YT) %external %routine %spec SET CELL (%integer CELL ID, WHICH, ONOFF) %external %routine %spec CIFSYS LEVEL (%integer I) %external %routine %spec CIFSYS MONITOR (%integer I) %external %string (63) %fn %spec CIFSYS ERROR (%integer I) %external %routine %spec D W DEF (%integer D, ID) %external %integer %fn %spec CIF CELL NUMBER (%integer CIFSYSID) ! Use of streams - in 1.... Secondary command file (USE) ! 1.... CIF input files (with include files) ! out 1 - Output from CELLS ! 2 - EDWIN PDF ! 3 - Other graphics output. ! For all systems - !%external %routine %spec SET DEFAULT (%string (7) EXT) %const %integer VAX = M'VAX', EMAS = M'EMAS' ! For VAX %const %integer MACHINE = VAX %const %string (1) SYSTEM = "A" %include "EDWIN:CONSTS.INC" %include "EDWIN:SPECS.INC" %include "EDWIN:SHAPES.INC" %include "EDWIN:TXSTACK.INC" %const %string (31) HELP FILE = "VLSI:CIFVIEW.DOC", USE DIR = "VLSI:" %const %string (7) CELLS EXT = ".LIS", CIF EXT = ".CIF", USE EXT = ".COM", PDF EXT = ".PDF", HP EXT = ".HP", GP EXT = ".GP-F80",LP EXT = ".LP" %const %string (3) TTIN = ":T", TTOUT = ":T" %include "Inc:FS.IMP" %include "Inc:Util.imp" %integer %fn SEXISTS (%string(127) FILE) %integer xno %on 3,9 %start; %result = FALSE; %finish xno = fcomm('S'<<8,file) %if xno > 0 %start xno = fcomm('H'<<8+Xno+'0',"") %result = TRUE %finish %result = FALSE %end ! For EMAS !%const %integer MACHINE = EMAS !%const %string (1) SYSTEM = "E" !%include "ECSLIB.EDWIN_CON" !%include "ECSLIB.EDWIN_INC" !%include "ECSLIB.EDWIN_GEO" !%include "ECSLIB.EDWIN_TXS" !%include "ECSC17.IMP77SPECS" ! !%const %string (31) HELP FILE = "ECSLIB.VLSIUSE_CIFVIEW", USE DIR = "ECSLIB.VLSIUSE_" !%const %string (5) CELLS EXT = "#LIS", CIF EXT = "#CIF", ! USE EXT = "", PDF EXT = "#PDF", HP EXT = "#HP", ! GP EXT = "#GP", LP EXT = "#LP" !%const %string (5) TTIN = ".IN", TTOUT = ".OUT" ! !%external %integer %fn %spec SEXISTS %alias "EXIST" (%string (255) FILE) !{ and remove the %begin block at the end of the file } %const %integer MAX LAYERS = 15 %own %integer N LAYERS = 10 %own %string (1) TECH = "?" %own %integer DEVICE = -1 %own %string (4) %array L NAMES (1 : MAX LAYERS) = "ND", "NP", "NM", "NI", "NB", "NC", "NG", "NV", "NX", "ZZZ" (*) %own %integer %array PERCENTS (1 : MAX LAYERS) = 18, 15, 18, 6, 3, 10, 1, 3, 1, 23, 0 (*) %const %integer DEF ILAP SCALE = 300; ! no. of 100ths micron/lambda. ! DEF LAYER COL the default colour of each layer %own %byte %integer %array DEF LAYER COL (1:MAX LAYERS) = 3,4,2,4,1(*) ! LAYER COL the colour of each layer %own %byte %integer %array LAYER COL (1:MAX LAYERS) = 3,4,2,4,1(*) ! LAYER STYLE is the line style used %own %byte %integer %array LAYER STYLE (1:MAX LAYERS) = 0 (3), 1, 0, 1, 0 (*) ! VALID is used to indicate if a layer is visible. %own %integer %array VALID (1:MAX LAYERS) = TRUE (*) %external %routine DO LAYER (%string (5) LAY) %const %integer ON = 1, OFF = 0 %integer L, MODE, COL, SHADE, RASTER RASTER = OFF RASTER = ON %if DEVICE=CHARLES %or DEVICE=SIGMA %c %or DEVICE=APM Level 1 %or DEVICE=BBC Micro %for L=1,1,N LAYERS %cycle %if LAY = L NAMES (L) %start SET LINE STYLE (LAYER STYLE (L)) COL = LAYER COL (L) MODE = OR MODE SHADE = SOLID %if CHARNO(LAY,2)='C' %start { Contacts } MODE = Replace Mode COL = 0 %if RASTER = ON %and LENGTH(LAY)=2 %finish %else %if CHARNO(LAY,2)='I' %or CHARNO(LAY,2)='W' %start SHADE = OUTLINE %if DEVICE=APM Level 1 %or DEVICE=BBC Micro SHADE = OUTLINE %if LAY="CWP" %finish %else %if LAY="NB" %start SHADE = OUTLINE COL = 1 %if RASTER = ON %finish SET COLOUR MODE (MODE) SET SHADE MODE (SHADE) SET COLOUR (COL) %return %finish %repeat UPDATE PRINT STRING ("Unknown layer - ".LAY) NEWLINE %signal 12 %end %external %routine DO TEXT (%integer SIZE, DIR, X, Y, %string (255) STR) SET CHAR SIZE (SIZE) SET CHAR ROT (DIR) MOVE ABS (X, Y) TEXT (STR) %end %external %routine GET WINDOW (%integer %name XL, XR, YB, YT) INQUIRE WINDOW (XL, XR, YB, YT) %end %external %routine DO MB BOX (%string (255) NAME, %integer XL, YL, XU, YU) ! Draws a Minimum Bounding BOX for cell. %integer SX, SY, DX, DY, ROT, DXU, DXL, DYU, DYL %const %integer WIDTH=4 SET LINE STYLE (0) %if DEVICE#CHARLES %start SET COLOUR (1) MOVE ABS (XL, YL) LINE ABS (XU, YL) LINE ABS (XU, YU) LINE ABS (XL, YU) LINE ABS (XL, YL) %else SET COLOUR MODE (Replace Mode) SET COLOUR (7) DXL = XL; DYL = YL DXU = XU; DYU = YU MAP TO DEVICE COORDS (DXL, DYL) MAP TO DEVICE COORDS (DXU, DYU) DRIVE DEVICE (12, DXL, DYL); DRIVE DEVICE (13, DXU, DYL+WIDTH) DRIVE DEVICE (12, DXU-WIDTH, DYL); DRIVE DEVICE (13, DXU, DYU) DRIVE DEVICE (12, DXL, DYU-WIDTH); DRIVE DEVICE (13, DXU, DYU) DRIVE DEVICE (12, DXL, DYL); DRIVE DEVICE (13, DXL+WIDTH, DYU) %finish %return %if NAME="" DX = XU - XL DY = YU - YL %if DY > DX %start SX = DX; DX = DY; DY = SX; ROT = 90 %finish %else ROT = 0 %cycle NAME = " " . NAME . " " %return %if LENGTH(NAME)>253 SX = DX//(LENGTH(NAME)) %return %if SX = 0 SY = DY//5; ! Max char size of 0.2 * DY %return %if SY = 0 %exit %if SY*2 > SX %repeat %if ROT#0 %then MOVE ABS (XL + 3*SY, YL) %else MOVE ABS (XL, YL + (3*SY)//2) SET CHAR SIZE (SX) SET CHAR ROT (ROT) TEXT (NAME) %end %external %routine DO BOX (%integer L, W, %record (POINTFM) %name C, D) ! Draw box of length L, width W, at centre C with direction vector D. BOX (L, W, C, D) %end %external %routine DO POLYGON (%integer NE, %record (POINTFM) %array %name P(1:*)) ! Draw a polygon with number of elements NE, contained in P. POLYGON (NE, P) %end %external %routine DO WIRE (%integer W, NP, %record (POINTFM) %array %name P(1:*)) ! Draw a wire of width W, with number of points NP, contained in P. WIRE (W, NP, P) %end !########################################################################### !# # !# T h e M a i n B o d y of C I F V I E W # !# # !########################################################################### %external %routine CIFVIEW (%string (255) PARAM) %const %string (31) DEVICE SET TO = "Current device set to be " %const %string (63) NOT PLOTTER = "Current device is not a plotter" %const %string (31) NOT COLOUR = "Unknown colour specified" %const %string (31) UNKNOWN STYLE = "Unknown line style specifed" %const %string (63) NO DIGITS = "Too few digits at the start of the parameter list" %const %string (63) NO TECHNOLOGY = "No technology set - Analyse some CIF" %const %real CM TO INS = 2.54; ! Convertion of Centimeters to inches %const %real MIN SIGNIFICANT LAMBDA = 0.001 %const %integer NO PLOTTER = 1; ! UNITS per CM set to this if it is not a plotter. %const %integer HELP=0, DEVIC=1, ANALYSE=2, USE=3, END=4, STOP=5, DRAW=6 %const %integer CALL=7, POINT=8, REDRAW=9, CELLS=10, LEVEL=11, ON=12, OFF=13 %const %integer SIZE=14, NCIRCLE=15, PAN=16, STORE=17, WINDO=18, LAYER=19 %const %integer MON=20, ROTATE=21, SCALE=22, SPEED=23, DELETE=24, SETLAM=25 %const %integer WIPE=26, BCALL=27, VSN=28, IDENT=29, MCALL=30, ZOOM=31 %const %integer WCALL=32, GRID=33 %const %integer LAST=GRID %conststring(7)%array KNOWN(0:LAST)=%c "HELP", "DEVICE", "ANALYSE", "USE", "END", "STOP", "DRAW", "CALL", "POINT", "REDRAW", "CELLS", "LEVEL", "ON", "OFF", "SIZE", "NCIRCLE", "PAN", "STORE", "WINDOW", "LAYERS", "%MON", "ROTATE", "SCALE", "SPEED", "DISPOSE", "SETLAM", "WIPE", "BCALL", "VERSION", "IDENT", "MCALL", "ZOOM", "WCALL", "GRID" %const %integer NO OF CLASHES=11 %const %string (3) %array AMBIGUOUS (1:NO OF CLASHES) = "D", "P", "R", "C", "S", "L", "O", "WI", "W", "STO", "ST" %switch EXEC(0:LAST) %integer ROUTINE, A, B, C, D, DX, DY, FACTOR, UNITS PER CM, I, XL, YB %integer %name ZWXL, ZWXR, ZWYT, ZWYB %integer CWXL, CWXR, CWYB, CWYT, ZSP, ROTATION %own %real %array ROT 90 AC (0:8) = 0, -1, 0, 1, 0, 0, 0, 0, 1 %own %real %array ROT 90 C (0:8) = 0, 1, 0, -1, 0, 0, 0, 0, 1 %record (TRANSFM) %name BASE TRANS %const %integer MAX ZOOM STACK = 7 %record %format ZOOMF (%integer XL, XR, YB, YT) %record (ZOOMF) %array ZOOMSTACK (0:MAX ZOOM STACK) %own %string (127) LAST CELL = "" %own %integer INIT = FALSE %own %integer TEK POS = -1; ! Unknown position %own %integer GRID SIZE = -1; ! Undefined (off) %own %integer ILAP SCALE = DEF ILAP SCALE %own %integer REQ LEVEL = TRANSFORM STACK DEPTH; ! Transformation stack size %own %integer RANDOM WINDOW = -1; ! <0 => not set, 0 => BB window, >0 => random window %own %integer COMMAND STREAM = 0 %own %real REQ LAMBDA = 0; ! 0 => not significant. %real RX, RY, RXO, RYO %const %integer MAX COM LEN = 255; ! Length of command words %const %integer MAX FILE LEN = 127; ! Length of filename string %const %integer MAX OUT LEN = 127; ! Length of output line %string (MAX FILE LEN) LAST FILE ANALED %string (MAX COM LEN) COMMAND, LINE, REST, TRASH %routine SWAP (%integer %name A, B) %integer C C = A; A = B; B = C %end %routine GET REPLY (%integer %name R) %integer I READ SYMBOL (R) %and R=R&95 %until R='Y' %or R='N' READ SYMBOL (I) %until I=NL %end %routine READ COMMAND LINE %integer CHAR %on 3,9 %start COMMAND="STOP" %return %finish LINE = "" COMMAND = "" %cycle READ SYMBOL (CHAR) TEKPOS = TEKPOS + 1 %if CHAR = NL %and TEKPOS>0 %repeat %until CHAR > ' ' %cycle CHAR = CHAR & 95 %if 'a'<=CHAR<='z' COMMAND = COMMAND.TO STRING (CHAR) READ SYMBOL (CHAR) %repeat %until CHAR <= ' ' %or LENGTH(COMMAND)=MAX COM LEN READ SYMBOL (CHAR) %while CHAR <= ' ' %and CHAR # NL %return %if CHAR = NL %cycle CHAR = CHAR & 95 %if 'a'<=CHAR<='z' LINE = LINE.TO STRING(CHAR) READ SYMBOL (CHAR) %repeat %until CHAR = NL %or LENGTH(LINE)=MAX COM LEN %end %routine MESSAGE (%string (255) S) PRINT STRING (S) NEWLINE %end %routine FAULT(%string(255) S) SELECT OUTPUT(0) MESSAGE (COMMAND." fails - ".S) COMMAND STREAM = 0; ! Reset to terminal if in a command file %signal 12 %end %routine OPEN WRITE(%integer STREAM, %string(MAX FILE LEN) FILE) %on 3,9 %start FAULT("Cannot access output file ".FILE) %finish FILE = TTOUT %if FILE="" OPEN OUTPUT (STREAM, FILE) %end %routine OPEN READ(%integer STREAM, %string(MAX FILE LEN) FILE) %on 3,9 %start FAULT("Cannot access input file ".FILE) %finish FILE = TTIN %if FILE="" OPEN INPUT (STREAM, FILE) %end %routine READ FROM STR (%integer ADDRESS, TYPE, %string (*) %name STR) ! TYPE = 0 to read an integer, or >0 for a real %integer sign, sym, limit, digit, ptr %longreal value, exp, base %routine SKIP SYMBOL PTR = PTR + 1 %end %integer %fn NEXT SYMBOL %signal 9 %if PTR>=length(STR) %result = charno (str, ptr+1) %end str = str." "; ! To avoid %signal 9 , unless nothing is there. ptr = 0 base = 10.0 sign = 1 %cycle sym = nextsymbol %if sym = '-' %start %signal 4,1 %if sign < 0 sign = -1 skipsymbol; sym = nextsymbol %exit %finish %exit %if sym >' ' %and sym#',' skipsymbol %repeat more: value = 0 limit = int(base) digit = -1; sym = sym - 32 %if 'a'<= sym <= 'z' digit = sym-'0' %if '0' <= sym <= '9' digit = sym -'A'+10 %if 'A'<=sym<='Z' %signal 4,1 %unless 0 <= digit < limit %or (sym = '.' %and type>0) %while 0 <= digit < limit %cycle skipsymbol value = value*base+digit sym = nextsymbol digit = -1; sym=sym-32 %if 'a'<=sym<='z' digit = sym-'0' %if '0'<=sym<='9' digit = sym-'A'+10 %if 'A'<=sym<='Z' %repeat %if sym = '_' %start base = value skipsymbol sym = nextsymbol ->more %finish %if sym = '.' %and limit = 10 %and type>0 %start skipsymbol exp = 0.1 %cycle sym = nextsymbol %exit %unless '0' <= sym <= '9' value = value+(sym-'0')*exp exp = exp*0.1 skipsymbol %repeat %finish %if sym = '@' %and limit = 10 %and type>0 %start skipsymbol read from str (addr(sym), 16_10<<24, LINE) value = value*10.0\sym %finish value = -value %if sign < 0 %if type=0 %start; !integral sym = int(value) integer(address) = sym %finish %else real(address) = value STR = SUB STRING (STR, PTR+1, LENGTH(STR)) %end %integer %fn DIGIT (%integername N) %on 3,4,5,9 %start %result = FALSE; ! No digit on LINE %finish READ FROM STR (ADDR(N), 0, LINE) %result = TRUE %end %integer %fn STOI %integer I %result = I %if DIGIT(I) = TRUE FAULT (NO DIGITS) %end %integer %fn RDIGIT (%real %name R) %on 3,4,5,9 %start %result = FALSE; ! No number on the line. %finish READ FROM STR (ADDR(R), 1, LINE) %result = TRUE %end %real %fn STOR %real R %result = R %if RDIGIT (R) = TRUE FAULT (NO DIGITS) %end %routine SPACES IN LINE FOR (%integer SYM) ! Replace all occurences of SYM in LINE by a space, & remove redundant spaces. %string (MAX COM LEN) REST %integer I %for I=1,1,LENGTH(LINE) %cycle CHARNO(LINE,I) = ' ' %if CHARNO(LINE,I)=SYM %repeat LINE = LINE." ".REST %while LINE -> LINE.(" ").REST %end %routine COPY FILE ! Make a copy of the current input to current output and then close input %integer I %on 3,9 %start CLOSE INPUT %return %finish %cycle READ SYMBOL (I) PRINT SYMBOL (I) %repeat %end %routine NEWFRAME IF INTERACTIVE DISPLAY NEWFRAME %if DEVICE=Terminal %or DEVICE=Tektronix - %or DEVICE=WESTWARD %or DEVICE=SIGMA %or DEVICE=HP 2648 %end %routine LIST HELP %integer S %on 3,9 %start %if Event_sub=1 %start MESSAGE ("Sorry, no help info on ".LINE) Close input %else MESSAGE ("Cannot open HELP file") %finish %return %finish %if LINE#"" %start %for S = 0,1,LAST %cycle %if KNOWN(S) -> TRASH.(LINE).REST %and TRASH="" %start LINE = KNOWN(S) ! allows the parameters to be abreviated. %exit %finish %repeat %else LINE="HELP" %finish NEWFRAME IF INTERACTIVE DISPLAY DRIVE DEVICE (1, 0, 0) %if DEVICE=BBC Micro TEKPOS = -1 OPEN INPUT (COMMAND STREAM + 1, HELP FILE) SELECT INPUT (COMMAND STREAM + 1) %cycle READ SYMBOL (S) %until S='!' %and NEXT SYMBOL='<' SKIP SYMBOL REST = "" READ SYMBOL (S) %and REST=REST.To String(S) %until NEXT SYMBOL = NL READ SYMBOL (S) %if LINE -> TRASH.(REST) %and TRASH="" %start %while %not (s='!' %and next symbol='>') %cycle print symbol (s) read symbol (s) %repeat close input %return %finish %repeat %end %routine MY UPDATE %integer A, B, C, D %if DEVICE=HP PLOTTER %and DEVICE DATA_MVX < 17000 %start INQUIRE VIEWPORT (A, B, C, D) VIEWPORT (0, 16000, 0, 11400) DRIVE DEVICE (4, 16000, 11400) SET COLOUR (0) UPDATE VIEWPORT (A, B, C, D) %else SET COLOUR (0) %if DEVICE=HP PLOTTER UPDATE %finish %end %routine PUSH ZOOM STACK %own %record (ZOOMF) %name Z ZSP = ZSP + 1 FAULT ("Zoom stack overflow") %if ZSP = MAX ZOOM STACK Z == ZOOM STACK (ZSP) ZWXL == Z_XL; ZWXR == Z_XR; ZWYB == Z_YB; ZWYT == Z_YT %end %routine POP ZOOM STACK FAULT ("Zoom stack is empty") %if ZSP = 0 ZSP = ZSP - 2 PUSH ZOOM STACK %end %routine INIT ZOOM STACK ZSP = -1 PUSH ZOOM STACK %end %routine SET UP DEVICE (%integer DEV) %string (MAX FILE LEN) FILE, REST %integer I FILE = LAST FILE ANALED ! Reduce FILE to just the name, according to the rules - ! DEV:[DIR]NAME.EXT;VER on VAX ! USER.PDNAME_NAME#EXT on EMAS %if FILE -> (":").FILE %start; %finish %if FILE -> ("]").FILE %start; %finish %if FILE -> FILE.(".").REST %start FILE = REST %if MACHINE = EMAS %finish %if FILE -> ("_").FILE %start; %finish %if FILE -> FILE.("#") %start; %finish REST = "" REST = GP EXT %if 563<=DEV<=1051 REST = HP EXT %if DEV=7220 REST = LP EXT %if DEV='L' %or DEV=132 %or DEV='P' %or DEV=120 %or DEV=300 %or DEV='G' %if REST#"" %start FILE = FILE.REST OPEN WRITE (3, FILE) MESSAGE ("Graphics data being sent to ".FILE) VIEW ON (3) %finish %else VIEW ON (0) INITIALISE FOR (DEV) DEVICE = DEVICE DATA_DEV NO UNITS PER CM = DEVICE DATA_UNITS PER CM %if UNITS PER CM # 0 %start VIEW PORT (0, 38*UNITS PER CM, 0, 26*UNITS PER CM) %else REQ LAMBDA = 0 %if DEVICE=Tektronix %or DEVICE=WESTWARD %start VIEW PORT (256, 1023, 0, 767) %else ! Use default Viewport %finish %finish %if DEVICE=CHARLES %or DEVICE=Tektronix %or DEVICE=SIGMA %c %or DEVICE=APM Level 1 %or DEVICE=WESTWARD %then I=1 %else I=0 SET CHAR QUALITY (I) SET CHAR SIZE (9) TEKPOS = -1 %end %routine NEW TEK POS ! Return to the correct Tektronix position. DRIVE DEVICE (4, 0, 780-TEKPOS*20); ! Move DRIVE DEVICE (7, 2, 7); ! Set char size to small. DRIVE DEVICE (2, 0, 0); ! Update %end %routine RESET ALL LAYERS ! Read in the contents of layer names, colours, styles and percentages. %string (5) %array NAMES (1: MAX LAYERS) %integer %array PERCENTAGES (1: MAX LAYERS) %byte %integer %array COLOUR, STYLE (1: MAX LAYERS) %integer I %routine READ NAME (%string (5) %name N) %string (255) T %integer I T = "" SKIP SYMBOL %while NEXT SYMBOL <=' ' %cycle READ SYMBOL (I) %unless ('A'<=I<='Z' %or '0'<=I<='9') %start SKIP SYMBOL %while NEXT SYMBOL # NL FAULT ("Invalid symbol in layer name") %finish T = T.TO STRING(I) %repeat %until NEXT SYMBOL <=' ' %if LENGTH(T)<=5 %then N = T %else %start SKIP SYMBOL %while NEXT SYMBOL # NL FAULT ("Layer name too long") %finish %end %on 1,2,3,4,5,6,7,8,9 %start FAULT ("Illegal format for layer".ITOS (I, 1)) %finish %if COMMAND STREAM = 0 %start PRINT STRING ("Enter layer identification according to the next line, and end with layer ""ZZZ""") NEWLINE PRINT STRING (" <% of data structure>") NEWLINE %finish PROMPT ("Data: ") %for I=1,1,MAX LAYERS %cycle READ NAME (NAMES(I)) %exit %if CHARNO (NAMES(I),1)='Z' READ (COLOUR(I)) READ (STYLE(I)) { Was Charles colour } READ (STYLE(I)) READ (PERCENTAGES(I)) %repeat N LAYERS = I READ SYMBOL (I) %until I=NL %for I=1,1,N LAYERS-1 %cycle L NAMES (I) = NAMES (I) DEF LAYER COL (I) = COLOUR (I) LAYER COL (I) = COLOUR (I) LAYER STYLE (I) = STYLE (I) PERCENTS (I) = PERCENTAGES (I) %repeat L NAMES (N LAYERS) = "ZZZ" LAYER COL (N LAYERS) = 1 LAYER STYLE (N LAYERS) = 0 PERCENTS (N LAYERS) = 0 TECH = SUB STRING (NAMES(1), 1, 1) %end %routine IDENTIFY (%integer LAYER, COLOUR, STYLE) %string (15) %fn COL %const %integer MAX COLOUR = 8 %const %string (7) %array COLOURS (1:MAX COLOUR) = "black", "blue", "green", "red", "purple", "yellow", "lime", "brown" %result = COLOURS(COLOUR) %if 1<=COLOUR<=MAX COLOUR %result = "colour".ITOS(COLOUR,1) %end %string (15) %fn STY %const %integer MAX STYLE = 4 %const %string (13) %array STYLES (1:MAX STYLE) = "dotted", "chain", "short dashed", "long dashed" %result = STYLES(STYLE) %if 1<=STYLE<=MAX STYLE %result = "normal" %end LAYER COL (LAYER) = COLOUR LAYER STYLE (LAYER) = STYLE MESSAGE ("Layer ".L NAMES(LAYER)." will be drawn in ".COL." and with ".STY." lines") %end %string(MAX OUT LEN) %fn LAYERS BEING DRAWN %integer I, ALL %string (MAX OUT LEN) R %const %string (31) DRAWN = " will be used for drawing" ALL = TRUE R = "" %for I=N LAYERS-1,-1,1 %cycle %if VALID(I)=TRUE %start R = R." + " %if R#"" R = R.LNAMES(I) %finish %else ALL = FALSE %repeat %result = "All layers".DRAWN %if ALL=TRUE %result = "Only bounding boxes will appear, (no layers active)" %if R="" R = " ".R R = "s".R %if LENGTH(R)>5 %result = "Only layer".R.DRAWN %end %routine DO ANALYSIS %routine CHOOSE TECHNOLOGY %integer SYM %routine GET DEFAULT LAYERS %string (4) MOS %integer CUR STREAM %on 3,9 %start COMMAND STREAM = COMMAND STREAM - 1 SELECT INPUT (CUR STREAM) %return %finish MOS = "MOS" CUR STREAM = DEFAULT DEVICE MOS = "MOS8" %if CUR STREAM='C' %or CUR STREAM='c' { Charles } %c %or CUR STREAM='I' %or CUR STREAM='i' { Igor } %c %or CUR STREAM='F' %or CUR STREAM='f' { Fred } %c %or CUR STREAM=5688 %or CUR STREAM=5982 { Sigma } %c %or CUR STREAM=16_BBC CUR STREAM = IN STREAM COMMAND STREAM = COMMAND STREAM + 1 OPEN INPUT (COMMAND STREAM, USEDIR.TECH.MOS.USEEXT) SELECT INPUT (COMMAND STREAM) SKIP SYMBOL %while NEXT SYMBOL # NL; ! Skip the command 'IDENT *' RESET ALL LAYERS CLOSE INPUT %signal 9 %end %on 3,9 %start RESET INPUT GET DEFAULT LAYERS %return %finish TECH = "N"; ! If all else fails use Nmos! %cycle READ SYMBOL (SYM) %until '0'<=SYM<='9' %or SYM='(' %or 'A'<=SYM<='Z' %if SYM = '(' %start READ SYMBOL (SYM) %until SYM = ')' %continue %finish %if SYM = 'L' %start READ SYMBOL (SYM) %until 'A'<=SYM<='Z' TECH = TO STRING (SYM) %signal 9 %finish READ SYMBOL (SYM) %until SYM=';' %repeat %end ROUTINE = ANALYSE LINE = TTIN %if LINE="" LINE = LINE.CIF EXT %if charno(line,1)#':' %and %not (LINE -> (".")) ! SET DEFAULT (CIF EXT) COMMAND STREAM = COMMAND STREAM + 1 OPEN READ (COMMAND STREAM, LINE) SELECT INPUT (COMMAND STREAM) PROMPT ("CIF text: ") LAST FILE ANALED = LINE CHOOSE TECHNOLOGY %if TECH="?" ANAL OR DRAW CIF (0, 0, NLAYERS, FACTOR, L NAMES, VALID, PERCENTS) CLOSE INPUT COMMAND STREAM = COMMAND STREAM - 1 %end %routine IDENTIFY CELL (%integer %name ID) ! This routine identifies a given cell an returns the result in ID. ! If the cell is not found it will never return, (fault signaled). %string (MAX OUT LEN) NAME ID = 0 NAME=LINE LINE="" %if LINE#"*" %and DIGIT (ID) = TRUE ID = FIND CELL (LINE, ID, CWXL, CWYB, CWXR, CWYT) FAULT ("Cell '".NAME."' not found") %if ID<0 %end %routine ROTATE WINDOW ! Change CWXL, CWXR, CWYB, CWYT to the values required for a 90' rotation. %return %if ROTATION = 0 %if ROTATION > 0 %start SWAP (CWYB, CWXL) SWAP (CWYT, CWXR) SWAP (CWYB, CWYT) CWYB = - CWYB; CWYT = - CWYT %else SWAP (CWYT, CWXL) SWAP (CWYB, CWXR) SWAP (CWYB, CWYT) CWXR = - CWXR; CWXL = - CWXL %finish %end %routine DRAW GRID ! Draw a grid over the current picture of size GRID SIZE %integer I, A CLIP ON SET COLOUR MODE (Replace Mode) SET COLOUR (1) A = REM (CWXR-CWXL, GRID SIZE) CWXR = CWXR + GRID SIZE - A %if A#0 A = REM (CWYT-CWYB, GRID SIZE) CWYT = CWYT + GRID SIZE - A %if A#0 I = CWXL %while I <= CWXR %cycle MOVE ABS (I, CWYT) LINE ABS (I, CWYB) I = I + GRID SIZE %repeat I = CWYB %while I <= CWYT %cycle MOVE ABS (CWXL, I) LINE ABS (CWXR, I) I = I + GRID SIZE %repeat SET COLOUR (1) MARKER ABS (1, 0, 0) %end %routine do layers %integer I, A, MODE, THIS BIT, CHAR %string (MAX COM LEN) LAYERS, REST %integer %array TVALID (1:MAX LAYERS) %if 'A'<=CHARNO(LINE,1)<='Z' %start ! Absolute layer settings TVALID(I) = FALSE %for I=1,1,MAX LAYERS LINE = "+".LINE %else ! Layer setting relative to the current settings TVALID(I) = VALID(I) %for I=1,1,MAX LAYERS %finish A = TRUE ! Generate a cannonical layer list - ! ()* -> (' ')* LAYERS = "" LINE = LINE." " THIS BIT = 1 %cycle %cycle CHAR = CHARNO(LINE, THIS BIT) THIS BIT = THIS BIT + 1 %repeat %until CHAR>' ' %or THIS BIT>LENGTH(LINE) %exit %if THIS BIT>LENGTH(LINE) %if CHAR='-' %then LAYERS=LAYERS."-" %else LAYERS=LAYERS."+" %while %not ('A'<=CHAR<='Z') %and THIS BIT < LENGTH(LINE) %cycle CHAR = CHARNO(LINE, THIS BIT) THIS BIT = THIS BIT + 1 %repeat LAYERS = LAYERS.TECH %unless THIS BIT <= LENGTH(LINE) %and 'A'<=CHARNO(LINE,THIS BIT)<='Z' %cycle LAYERS = LAYERS.TO STRING (CHAR) %exit %if THIS BIT = LENGTH(LINE) CHAR = CHARNO(LINE, THIS BIT) THIS BIT = THIS BIT + 1 %repeat %until %not ('A'<=CHAR<='Z' %or '0'<=CHAR<='9') THIS BIT = THIS BIT - 1 %if CHAR='-' LAYERS = LAYERS." " %repeat %until THIS BIT >= LENGTH(LINE) %cycle REST = "" %if LAYERS -> LAYERS.(" ").REST %start; %finish %if CHARNO(LAYERS,1)='-' %then MODE=FALSE %else MODE=TRUE LAYERS = SUB STRING (LAYERS, 2, LENGTH(LAYERS)) %for I=1,1,N LAYERS %cycle TVALID(I) = MODE %and %exit %if LAYERS=LNAMES(I) A = FALSE %if I=N LAYERS %repeat %exit %if A#TRUE LAYERS = REST %repeat %until REST="" %if A=FALSE %then MESSAGE ("Unknown layer - '".LAYERS."'") %else %start VALID(I) = TVALID(I) %for I=1,1,N LAYERS %finish %end !*********************************************************************** !* * !* Main Program starts here - * !* * !*********************************************************************** %on %event 9,10,11,12,13,14 %start UPDATE MESSAGE ("EDWIN error - ".EDWIN ERROR(EVENT_SUB)) %if EVENT_EVENT=14 MESSAGE ("CIFSYS fails - ".CIFSYS ERROR(EVENT_SUB)) %if EVENT_EVENT=13 %return %if INIT # TRUE %finish %if INIT # TRUE %start; ! Initialise ROTATION = 0 {none} INIT ZOOM STACK COMMAND = "CIFVIEW" ! FACTOR = 4 FACTOR = free store FACTOR = FACTOR - 70000 { A guess for the size of arrays etc } FAULT ("Not enough memory for the data structure") %if FACTOR < 10000 ! FACTOR = FACTOR * 2 %while PARAM -> ("/BIG").PARAM ! PARAM = PARAM.REST %while PARAM -> PARAM.(" ").REST LAST FILE ANALED = "T" INITIALISE FOR (0) SET UP DEVICE (0) %while PARAM#"" %cycle LINE=PARAM %and PARAM="" %unless PARAM -> LINE.(",").PARAM ! Note that LINE is used to give the filename to DO ANALYSIS. DO ANALYSIS %repeat NEWLINE SET UP DEVICE (DEFAULT DEVICE) MESSAGE (DEVICE SET TO.DEVICE DATA_NAME) INIT = TRUE %finish %cycle %cycle SELECT INPUT (COMMAND STREAM) SELECT OUTPUT (0) NEWLINE %if COMMAND STREAM = 0 %and COMMAND#"CELLS" PROMPT ("CIF: ") %if DEVICE=Tektronix %start TEKPOS = -1 %if TEKPOS > 30 TEKPOS = TEKPOS+3 %and NEW TEK POS %if TEKPOS>=0 %finish %else %if DEVICE=BBC Micro %start DRIVE DEVICE (0, 16_BBC, 0) %if COMMAND="CELLS" %or COMMAND="HELP" %finish READ COMMAND LINE %for I=1,1,NO OF CLASHES %cycle COMMAND="CIFVIEW" %and FAULT ("Command is ambiguous") %if COMMAND=AMBIGUOUS(I) %repeat %for I=0,1,LAST %cycle %if KNOWN(I)->TRASH.(COMMAND).REST %and TRASH="" %start COMMAND = KNOWN (I) ROUTINE = I -> EXEC (ROUTINE) %finish %repeat LINE = USEDIR.COMMAND %and -> EXEC (USE) %if SEXISTS(USEDIR.COMMAND.USE EXT)=TRUE MESSAGE ("CIFVIEW fails - Command ".COMMAND." not known") %repeat EXEC(HELP): ! Use VIEW to look at the HELP information LIST HELP %continue EXEC(DEVIC): ! Find device to be used. FAULT ("No device specified") %if LINE="" %if LINE#"?" %start I = -1 A = CHARNO (LINE,1) I = A %if 'A'<=A<='Z' %if I<0 %start %signal 14, 0 %unless '0'<=CHARNO(LINE,1)<='9' I = STOI %finish TERMINATE EDWIN ! %if I#0 %and MACHINE=VAX %start ! LINE = LINE.REST %while LINE -> LINE.(" ").REST ! LINE = "TT" %if LINE="" ! SET IN (LINE) ! SET OUT (LINE) ! %finish SET UP DEVICE (I) %finish MESSAGE (DEVICE SET TO.DEVICE DATA_NAME) WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) %if RANDOM WINDOW >= 0 %continue EXEC(DELETE): ! Delete the cell specified & all the numbers above it. %if LINE="*" %then C = 0 %else %start IDENTIFY CELL (C) C = CIF CELL NUMBER (C) %finish D W DEF ('D', C) MESSAGE ("Cells with numbers >= ".ITOS(C,0)." deleted") %continue EXEC(ANALYSE): DO ANALYSIS %continue EXEC(USE): FAULT ("No file specified") %if LINE="" LINE = LINE.USE EXT %if charno(line,1)#':' %and %not (LINE -> (".")) ! SET DEFAULT (USE EXT) LINE=USEDIR.LINE %if SEXISTS(USEDIR.LINE)=TRUE OPEN READ (COMMAND STREAM + 1, LINE) COMMAND STREAM = COMMAND STREAM + 1 %continue EXEC(END): EXEC(STOP): %if COMMAND STREAM > 0 %start COMMAND STREAM = COMMAND STREAM - 1 CLOSE INPUT %continue %finish TERMINATE EDWIN %return EXEC(ROTATE): ! Specify a base rotation for future calls %if LINE#"?" %start %if LINE="" %start ROTATION = 0 %else A = CHARNO (LINE,1) %if A='+' %or LINE="90" %start ROTATION = -1 BASE TRANS == record(addr(ROT 90 C(0))) %finish %else %if A='-' %start ROTATION = 1 BASE TRANS == record(addr(ROT 90 AC(0))) %else MESSAGE ("Parameter '".LINE."' invalid, options are '+90', '-90' '?' or none") %continue %finish %finish LAST CELL = "" { since window will now be wrong! } RANDOM WINDOW = -1 ZSP = 0 %finish %if ROTATION < 0 %start LINE = "90 degrees anti-clockwise" %finish %else %if ROTATION=0 %start LINE = "unity" %else { > 0 } LINE = "90 degrees clockwise" %finish MESSAGE ("Current base rotation is ".LINE) %continue EXEC(REDRAW): ! Redraw the last cell FAULT ("Use the comand DRAW to draw a cell") %if LAST CELL="" FAULT ("Only the last cell may be redrawn") %if LINE#"" LINE = LAST CELL IDENTIFY CELL (C) -> EXEC (WIPE) EXEC(MCALL): EXEC(BCALL): COMMAND = "DRAW"; ROUTINE = DRAW EXEC(DRAW): ! Does implicit call of WIPE after setting the window to be the BB of cell IDENTIFY CELL (C) INIT ZOOM STACK RANDOM WINDOW = 0 CLIP OFF ROTATE WINDOW %if ROTATION#0 WINDOW (CWXL, CWXR, CWYB, CWYT) INQUIRE WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) EXEC(WIPE): NEWFRAME TEKPOS = 0; ! Reset Tektronix page. UPDATE %and %continue %if ROUTINE=WIPE EXEC(CALL): FAULT ("No window set (you probably want the command DRAW)") %if RANDOM WINDOW<0 IDENTIFY CELL (C) %if ROUTINE = CALL LAST CELL = ItoS (Cif cell number(C), 0) INIT TRANSFORM PUSH TRANSFORM (BASE TRANS) %if ROTATION#0 %if REQ LAMBDA>MIN SIGNIFICANT LAMBDA %start INQUIRE WINDOW (CWXL, CWXR, CWYB, CWYT) XL = CWXL YB = CWYB RX = |(CWXR-CWXL)| RY = |(CWYT-CWYB)| INQUIRE VIEWPORT (A, I, B, D) ! DX & DY are set to be the window per sheet of paper DX = int ((I-A) * ILAP SCALE / UNITS PER CM / REQ LAMBDA) DY = int ((D-B) * ILAP SCALE / UNITS PER CM / REQ LAMBDA) %if RX > DX %or RY > DY %start UPDATE PRINT STRING ("The design will not fit on one sheet of paper at the current lambda setting") NEWLINE PROMPT ("Do you wish to plot it over".ItoS (int(RX/DX+0.5) * int(RY/DY+0.5), 1)." sheets (Y/N)?") GET REPLY (A) %continue %if A = 'N' RANDOM WINDOW = 1 CLIP ON PROMPT ("Do you want to plot all the sheets (Y/N)?") GET REPLY (A) ! Now Draw them D = 0; ! The plot number. INIT TRANSFORM PUSH TRANSFORM (BASE TRANS) %if ROTATION#0 %cycle CWXL = XL %cycle D = D + 1 %if A='N' %start; ! Selective plotting PROMPT ("Do you want to plot sheet".ITOS (D, 1)." (Y/N)?") GET REPLY (B) %finish %else B = 'Y' %if B='Y' %start NEWFRAME WINDOW (CWXL, CWXL + DX, CWYB, CWYB + DY) ANAL OR DRAW CIF (DRAW, C, NLAYERS, FACTOR, L NAMES, VALID, PERCENTS) MARKER ABS (6, CWXL, CWYB) MARKER ABS (6, CWXL+DX, CWYB) MARKER ABS (6, CWXL+DX, CWYB+DY) MARKER ABS (6, CWXL, CWYB+DY) MY UPDATE %finish CWXL = CWXL + DX %repeat %until CWXL >= CWXR CWYB = CWYB + DY %repeat %until CWYB >= CWYT WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) %continue %finish CWXL = CWXL - INT((DX - RX)/2) CWXR = CWXR + INT((DX - RX)/2) CWYB = CWYB - INT((DY - RY)/2) CWYT = CWYT + INT((DY - RY)/2) WINDOW (CWXL, CWXR, CWYB, CWYT) %finish ANAL OR DRAW CIF (DRAW, C, NLAYERS, FACTOR, L NAMES, VALID, PERCENTS) DRAW GRID %if GRID SIZE > 0 %and ROUTINE#CALL DRIVE DEVICE (4, 0, 22) %if DEVICE=Terminal; ! Move to top left of the screen MY UPDATE %continue EXEC(CELLS): !SET DEFAULT (CELLS EXT) A = 17 { Lines/page } %if LINE#"" %start OPEN WRITE (1, LINE) SELECT OUTPUT (1) I = FALSE { Interactive? } %else NEWFRAME IF INTERACTIVE DISPLAY DRIVE DEVICE (1, 0, 0) %if DEVICE=BBC Micro I = TRUE %finish LIST CELLS (ILAP SCALE, I, A) CLOSE OUTPUT %if LINE#"" TEKPOS = -1 %continue EXEC(LEVEL): ! The level of the data structure hierarchy which is to be interpreted %if LINE#"?" %start %if LINE#"" %start REQ LEVEL = STOI %else REQ LEVEL = -1 %finish REQ LEVEL = TRANSFORM STACK DEPTH %if REQ LEVEL < 0 CIFSYS LEVEL (REQ LEVEL) %finish MESSAGE ("Level set to ".ITOS(REQ LEVEL,0)) %continue EXEC(NCIRCLE): I = STOI I = 15 %if I<10 SET CHORD STEP (I) MESSAGE ("Circles will now be drawn with a chord step of ".ITOS(I,0)." degrees") %continue EXEC(STORE): ! Store an EDWIN PDF %if LINE="" %start STORE OFF LINE = "PDF storing disabled" %else %if LINE#"?" %start LINE = LINE.PDF EXT %if charno(line,1)#':' %and %not (LINE -> (".")) ! SET DEFAULT (PDF EXT) OPEN WRITE (2, LINE) STORE ON (2) %finish SELECT OUTPUT (2) LINE = "An EDWIN PDF is being dumped into ".OUT FILE NAME %finish SELECT OUTPUT (0) MESSAGE (LINE) %continue EXEC(PAN): ! Either PAN X Y which moves the window by a relative X Y, or new window offset by the distance between cursor points. FAULT ("Use DRAW to look at a cell") %if LAST CELL = "" INQUIRE WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) %if LINE#"" %start { point supplied as a parameter } A = STOI * ILAP SCALE B = 0 %unless DIGIT(B)=TRUE B = B * ILAP SCALE %else MESSAGE ("Give the displacement by entering two points by the cursor") SET COLOUR (1) REQUEST INPUT (I, A, B) MARKER ABS (6, A, B) DX = A; DY = B MAP TO DEVICE COORDS (DX, DY) %cycle REQUEST INPUT (I, C, D) %if DEVICE=CHARLES %or A=C %or B=D %start MAP TO DEVICE COORDS (C, D) %continue %if |DX-C| <= 5 %and |DY-D| <= 5 MAP TO VIRTUAL COORDS (C, D) %finish %exit %repeat MARKER ABS (6, C, D) UPDATE A = A - C; B = B - D %finish ZWXL = ZWXL + A; ZWXR = ZWXR + A ZWYB = ZWYB + B; ZWYT = ZWYT + B WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) CLIP ON ROUTINE = REDRAW; LINE = "" -> EXEC (REDRAW) EXEC(ZOOM): FAULT ("Use DRAW to look at a cell") %if LAST CELL = "" ROUTINE = WINDO %if LINE="?" EXEC(WINDO): %if LINE -> ("^") %start POP ZOOM STACK WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) %finish %else %if LINE#"?" %start PUSH ZOOM STACK CLIP ON %if LINE#"" %start CWXL = STOI * ILAP SCALE CWYB = STOI * ILAP SCALE CWXR = STOI * ILAP SCALE CWYT = STOI * ILAP SCALE %finish %else %if DEVICE=APM Level 1 %start PRINT STRING ( %c "Use the mouse to select the required window. Centre button selects the window, Left button decreases the window size, Right button increases the window size.") NEWLINE AREA INPUT (CWXL, CWYB, CWXR, CWYT) %else SET COLOUR (1) REQUEST INPUT (I, CWXL, CWYB) MARKER ABS (6, CWXL, CWYB) %cycle REQUEST INPUT (I, CWXR, CWYT) %if DEVICE=CHARLES %or CWXL=CWXR %or CWYB=CWYT %start A = CWXL; B = CWYB; C = CWXR; D = CWYT MAP TO DEVICE COORDS (A, B) MAP TO DEVICE COORDS (C, D) %continue %if |A-C| <= 5 %or |B-D| <= 5 %finish %exit %repeat MARKER ABS (6, CWXR, CWYT) UPDATE NEW TEK POS %and NEWLINES (2) %if DEVICE = TEKTRONIX %finish SWAP (CWXL, CWXR) %if CWXL>CWXR SWAP (CWYB, CWYT) %if CWYB>CWYT WINDOW (CWXL, CWXR, CWYB, CWYT) RANDOM WINDOW = 1 %finish INQUIRE WINDOW (ZWXL, ZWXR, ZWYB, ZWYT) ! Convert to Lambda A = INT (ZWXL/ILAP SCALE) B = INT (ZWXR/ILAP SCALE) C = INT (ZWYB/ILAP SCALE) D = INT (ZWYT/ILAP SCALE) MESSAGE ("Window set between ".ITOS(A,0).",".ITOS(C,0)." and ".ITOS(B,0).",".ITOS(D,0)) %continue %if ROUTINE=WINDO ROUTINE = REDRAW; LINE = "" -> EXEC(REDRAW) EXEC(LAYER): ! Alter the array of layers that are to be drawn. FAULT (NO TECHNOLOGY) %if TECH = "?" %if LINE="" %start VALID (I) = TRUE %for I=1,1,MAX LAYERS MESSAGE ("All layers will now be drawn") %continue %finish do layers %if LINE#"?" MESSAGE (LAYERS BEING DRAWN) %continue EXEC(MON): CIFSYS MONITOR (STOI) %continue EXEC(GRID): ! Draw a Grid over the current picture. %if LINE#"?" %start %if LINE -> ("OF") %then GRID SIZE = -1 %else %start GRID SIZE = 1 %unless DIGIT (GRID SIZE) = TRUE GRID SIZE = GRID SIZE * ILAP SCALE DRAW GRID %if RANDOM WINDOW >= 0 %finish %finish MESSAGE ("Grid drawing is suppressed") %and %continue %if GRID SIZE < 0 A = GRID SIZE %if LINE="?" %or LINE -> ("ON") %start LINE = "will be drawn after each cell displayed" %else LINE = "drawn" GRID SIZE = -1 %finish UPDATE MESSAGE (ITOS(INT(A/ILAP SCALE),0)." lambda grid ".LINE) %continue EXEC(IDENT): ! Assign the layer to be done in approprate colour/style RESET ALL LAYERS %and %continue %if LINE="*" FAULT (NO TECHNOLOGY) %if TECH = "?" MESSAGE ("Parameters should be '