-- PlaMakerImpl.mesa -- a program to run within Chipmonk -- written by E. McCreight, August 7, 1981 3:52 PM -- modified by Cary Kornfeld, October 1, 1981 10:11 AM -- modified by E. McCreight, April 25, 1984 10:36:28 am PST DIRECTORY IODefs, InlineDefs, ppddefs, ppdefs, ppdddefs, SegmentDefs, StreamDefs, StringDefs, SystemDefs, ZoneAllocDefs; PlaMakerImpl: PROGRAM IMPORTS InlineDefs, ppdddefs, ppddefs, ppdefs, SegmentDefs, StreamDefs, IODefs, StringDefs, ZoneAllocDefs = BEGIN OPEN ppdddefs, ppddefs, ppdefs, io: IODefs; Z: UNCOUNTED ZONE _ ZoneAllocDefs.GetAnXMZone[]; Punt: SIGNAL = CODE; -- All of the peripheral cells must contain an adjacent pair of bits, and -- all of the center cells must contain a rectangular quad of bits Cell: TYPE = LONG POINTER TO object _ NIL; DCell: TYPE = ARRAY BOOLEAN --data in cell-- OF Cell; DCellPr: TYPE = ARRAY BOOLEAN -- data in even cell -- OF DCell; MAXIDLENGTH: CARDINAL = 100; StopCODE: CHARACTER = '* ; HASHSIZE: CARDINAL = 29; --May be small for big PLA's nameIndex: TYPE = [0..MAXIDLENGTH); hashIndex: TYPE = [0..HASHSIZE); IOLink: TYPE = LONG POINTER TO IO; PTermLink: TYPE = LONG POINTER TO ProductTerm; IOTermLink: TYPE = LONG POINTER TO IOTerm; States: TYPE = {Absent, Assert, Invert}; TBStates: TYPE = {bottom, top}; Direction: TYPE = {vertical, horizontal, diagonal, up, down, left, right, upAndLeft, upAndRight, downAndLeft, downAndRight}; IO: TYPE = RECORD[ next: IOLink, TopBottom: TBStates, position: CARDINAL, name: SEQUENCE length: CARDINAL OF CHARACTER]; ProductTerm: TYPE = RECORD[ next: PTermLink, output: IOTermLink, input: IOTermLink]; IOTerm: TYPE = RECORD[ term: SEQUENCE tcount: CARDINAL OF States]; IOLIST: TYPE = RECORD[node: SEQUENCE IOcount: CARDINAL OF IOLink]; HashTable: TYPE = ARRAY hashIndex OF IOLink; hashPTerm: ARRAY hashIndex OF PTermLink; inputs, outputs: HashTable; inCount, outCount: CARDINAL; inputList, outputList: LONG POINTER TO IOLIST; Scount: INTEGER _ 0; PTermCount, boistCount, minBoistSpace: CARDINAL; --in: StreamDefs.StreamHandle; line: STRING _ [MAXIDLENGTH]; lineIn: STRING _ [MAXIDLENGTH]; eol: BOOLEAN; PLADecoder, PLAData: DCellPr; PLADecoderData, PLADecoderDataTop, PLADecoderDataBottom, PLADecoderTopLeftCorner, PLADecoderBottomLeftCorner, PLADecoderLeftGnd, PLADecoderGnd, PLADecoderDataGnd, PLADataHGnd, PLADataVGnd, PLADataGnd, PLADataTopGnd, PLADataBottomGnd, PLADataRightGnd, PLADataTopRightCorner, PLADataRight, PLADataBottomRightCorner: Cell; PLADecoderLeft, PLADataTop, PLADataBottom, PLADecoderTop, PLADecoderBottom, PLAOutMux: DCell; -- column: FALSE => even column, TRUE => odd column decodeCell, dataCell: Cell; -- samples for measurements RdID: PROCEDURE [id: STRING] = BEGIN inComment: BOOLEAN _ FALSE; i: nameIndex _ 0; prevChar: CHARACTER _ ' ; char: CHARACTER _ io.ReadChar[]; WHILE char = io.SP OR char = io.TAB OR char = io.CR OR char = io.LF DO char _ io.ReadChar[]; ENDLOOP; WHILE char # io.CR DO SELECT TRUE FROM inComment AND char = '- AND prevChar = '- => {char _ ' ; inComment _ FALSE}; inComment => NULL; char = io.SP OR char = io.LF OR char = io.TAB => EXIT; char = '- AND prevChar = '- => {char _ ' ; inComment _ TRUE; i _ i-1}; ENDCASE => {id[i] _ char; i _ i + 1}; prevChar _ char; char _ io.ReadChar[]; ENDLOOP; id^.length _ i; eol _ (char = io.CR OR char = io.LF); END; ReadIO: PROCEDURE [StopCode: CHARACTER] RETURNS [count: CARDINAL _ 0, hashTable: HashTable] = BEGIN Term: IOLink; id: STRING _ [MAXIDLENGTH]; id2: STRING _ [MAXIDLENGTH]; TB: TBStates; k, i, hash: CARDINAL; FOR i IN hashIndex DO hashTable[i] _ NIL ENDLOOP; DO -- get the name of the IO term and its position RdID[id]; IF id[0] = StopCode THEN EXIT; hash _ hashCode[id]; RdID[id2]; IF id2[0] = 't OR id2[0] = 'T THEN TB _ top ELSE TB _ bottom; -- create an IO node Term _ Z.NEW[IO[id.length]]; Scount _ Scount + 1; BEGIN OPEN Term; TopBottom _ TB; position _ count; count _ count + 1; FOR k IN [0..id.length) DO name[k] _ id[k]; ENDLOOP; next _ hashTable[hash]; hashTable[hash] _ Term; END; ENDLOOP; RETURN[count, hashTable]; END; ReadPTerms: PROCEDURE [] = BEGIN PTerm, PT: PTermLink _ NIL; id: STRING _ [MAXIDLENGTH]; alloc: BOOLEAN _ TRUE; done, found: BOOLEAN _ FALSE; k, outID, hash: CARDINAL _ 0; PTermCount _ 0; DO -- allocate a new Product Term Node IF alloc THEN BEGIN alloc _ FALSE; PTerm _ Z.NEW[ProductTerm]; PTerm.input _ Z.NEW[IOTerm[inCount]]; PTerm.output _ Z.NEW[IOTerm[outCount]]; Scount _ Scount + 3; PTermCount _ PTermCount + 1; END; FOR k IN [0..inCount) DO PTerm.input.term[k] _ Absent; ENDLOOP; FOR k IN [0..outCount) DO PTerm.output.term[k] _ Absent; ENDLOOP; -- get the output term RdID[id]; IF id[0] = '* THEN EXIT; outID _ lookUp[id, outputs]; PTerm.output.term[outID] _ Assert; -- discard the syntactic separator '=' RdID[id]; -- get the input terms hash _ 0; done _ FALSE; WHILE NOT done DO RdID[id]; k _ lookUp[id, inputs]; hash _ hash + k; IF id[0] = '- THEN PTerm.input.term[k] _ Invert ELSE PTerm.input.term[k] _ Assert; -- discard syntactic separator RdID[id]; done _ id[0] = '; ; ENDLOOP; -- insert the Product Term into the PTerm matrix IF hash >= HASHSIZE THEN hash _ hash MOD HASHSIZE; PT _ hashPTerm[hash]; found _ FALSE; DO IF PT=NIL THEN EXIT ELSE found _ TRUE; FOR k IN [0..inCount) UNTIL NOT found DO found _ PT.input.term[k] = PTerm.input.term[k]; ENDLOOP; IF found THEN EXIT ELSE PT _ PT.next; ENDLOOP; IF found THEN PT.output.term[outID] _ Assert ELSE BEGIN PTerm.next _ hashPTerm[hash]; hashPTerm[hash] _ PTerm; alloc _ TRUE; END; ENDLOOP; -- release unused PTerm node space IF NOT alloc THEN BEGIN Z.FREE[@PTerm.input]; Z.FREE[@PTerm.output]; Z.FREE[@PTerm]; Scount _ Scount - 3; PTermCount _ PTermCount - 1; END; END; FreeBlocks: PROCEDURE[] = BEGIN IOPtr, IOTemp: IOLink; p, pTemp: PTermLink; i: hashIndex; -- release space for input and output node lists Z.FREE[@inputList]; Z.FREE[@outputList]; Scount _ Scount - 2; -- release node space for input terms FOR i IN hashIndex DO FOR IOPtr_inputs[i], IOTemp UNTIL IOPtr=NIL DO IOTemp _ IOPtr.next; Z.FREE[@IOPtr]; Scount _ Scount - 1; ENDLOOP; ENDLOOP; -- release node space for output terms FOR i IN hashIndex DO FOR IOPtr_outputs[i], IOTemp UNTIL IOPtr=NIL DO IOTemp _ IOPtr.next; Z.FREE[@IOPtr]; Scount _ Scount - 1; ENDLOOP; ENDLOOP; -- release node space for product terms FOR i IN hashIndex DO FOR p _ hashPTerm[i], pTemp UNTIL p=NIL DO pTemp _ p.next; Z.FREE[@p.output]; Z.FREE[@p.input]; Z.FREE[@p]; Scount _ Scount - 3; ENDLOOP; ENDLOOP; END; hashCode: PROCEDURE [name: STRING] RETURNS [hashIndex] = BEGIN j: nameIndex; i: INTEGER; Start: CARDINAL; Start _ i _ 0; IF name[0] = '- THEN Start _ 1; FOR j IN [Start..name^.length) DO i _ i*10 + (name[j] - '0); IF name[j] >= 'a THEN i _ i - 32; --hash on upper case only ENDLOOP; i _ i MOD HASHSIZE; RETURN[IF i < 0 THEN i + HASHSIZE ELSE i]; END; strcmp: PROCEDURE [s: STRING, n: IOLink] RETURNS [BOOLEAN] = BEGIN i: INTEGER; Off, j: nameIndex; Off _ 0; IF s[0] = '- THEN Off _ 1; FOR j _ 0, j + 1 UNTIL j = s.length-Off DO i _ n.name[j] - s[j+Off]; --check for equality regardless of case IF i = 0 THEN LOOP; IF i = 32 AND s[j] >= 'A THEN LOOP; IF i = -32 AND s[j] >= 'a THEN LOOP; RETURN[FALSE]; REPEAT FINISHED => RETURN[TRUE] ENDLOOP; END; lookUp: PROCEDURE [s: STRING, hashTable: HashTable] RETURNS [CARDINAL] = BEGIN n: IOLink; h: hashIndex; h _ hashCode[s]; FOR n _ hashTable[h], n^.next UNTIL n = NIL DO IF strcmp[s, n] THEN RETURN[n.position] ENDLOOP; RETURN[0]; END; BuildProductTerms: PROCEDURE [si: StreamDefs.StreamHandle] = BEGIN -- called once in main line: STRING _ [MAXIDLENGTH]; i: hashIndex; IOPtr: IOLink; echo: BOOLEAN; saveIn: StreamDefs.StreamHandle; FOR i IN hashIndex DO hashPTerm[i] _ NIL ENDLOOP; eol _ FALSE; saveIn _ io.GetInputStream[]; io.SetInputStream[si]; echo _ io.SetEcho[FALSE]; -- read Input terms and build input term hash table [inCount, inputs] _ ReadIO[StopCODE]; -- read output terms and build output term hash table [outCount, outputs] _ ReadIO[StopCODE]; -- build IO List of IO descriptors arranged by position inputList _ Z.NEW[IOLIST[inCount]]; outputList _ Z.NEW[IOLIST[outCount]]; Scount _ Scount + 2; FOR i IN hashIndex DO FOR IOPtr_inputs[i], IOPtr.next UNTIL IOPtr=NIL DO inputList[IOPtr.position] _ IOPtr; ENDLOOP; ENDLOOP; FOR i IN hashIndex DO FOR IOPtr_outputs[i], IOPtr.next UNTIL IOPtr=NIL DO outputList[IOPtr.position] _ IOPtr; ENDLOOP; ENDLOOP; -- input the product terms and build the product term matrix ReadPTerms; io.SetInputStream[saveIn]; [] _ io.SetEcho[echo]; END; FindPLACells: PROCEDURE [cellFamily: STRING] = BEGIN PLADecoder _ FindDCellPr[cellFamily: cellFamily, required: TRUE, memberPrefix: "Decoder"L]; decodeCell _ PLADecoder[TRUE][FALSE]; PLADecoderTop _ FindDCell[ cellFamily: cellFamily, memberPrefix: "DecoderTop"L]; PLADecoderBottom _ FindDCell[ cellFamily: cellFamily, memberPrefix: "DecoderBottom"L]; PLADecoderLeft _ FindDCell[ cellFamily: cellFamily, memberPrefix: "DecoderLeft"L, vCompat: decodeCell]; PLADecoderTopLeftCorner _ FindCell[ cellFamily: cellFamily, member: "DecoderTopLeftCorner"L]; PLADecoderBottomLeftCorner _ FindCell[ cellFamily: cellFamily, member: "DecoderBottomLeftCorner"L]; PLAData _ FindDCellPr[cellFamily: cellFamily, required: TRUE, memberPrefix: "Data"L]; dataCell _ PLAData[FALSE][FALSE]; CheckPitchCompatability[decodeCell, dataCell, vertical, [1, 2], [1, 1]]; PLADecoderData _ FindCell[ cellFamily: cellFamily, member: "DecoderData"L, vCompat: dataCell]; PLADecoderDataTop _ FindCell[ cellFamily: cellFamily, member: "DecoderDataTop"L, hCompat: PLADecoderData]; PLADecoderDataBottom _ FindCell[ cellFamily: cellFamily, member: "DecoderDataBottom"L, hCompat: PLADecoderData]; PLADataTop _ FindDCell[ cellFamily: cellFamily, memberPrefix: "DataTop"L, hCompat: dataCell]; -- PLADataBottom _ FindDCell[ -- cellFamily: cellFamily, memberPrefix: "DataBottom"L]; PLAOutMux _ FindDCell[cellFamily: cellFamily, memberPrefix: "OutMux"L]; CheckPitchCompatability[dataCell, PLAOutMux[FALSE], horizontal, [1, 1], [1, 1]]; PLADataRight _ FindCell[ cellFamily: cellFamily, member: "DataRight"L, vCompat: dataCell]; PLADataTopRightCorner _ FindCell[ cellFamily: cellFamily, member: "DataTopRightCorner"L]; PLADataBottomRightCorner _ FindCell[ cellFamily: cellFamily, member: "DataBottomRightCorner"L]; PLADecoderLeftGnd _ FindCell[ cellFamily: cellFamily, member: "DecoderLeftGnd"L]; PLADecoderGnd _ FindCell[ cellFamily: cellFamily, member: "DecoderGnd"L, vCompat: PLADecoderLeftGnd, hCompat: decodeCell]; PLADecoderDataGnd _ FindCell[ cellFamily: cellFamily, member: "DecoderDataGnd"L, hCompat: PLADecoderData]; PLADataHGnd _ FindCell[ cellFamily: cellFamily, member: "DataHGnd"L, vCompat: PLADecoderGnd, hCompat: dataCell]; PLADataGnd _ FindCell[ cellFamily: cellFamily, member: "DataGnd"L, vCompat: PLADataHGnd]; PLADataVGnd _ FindCell[ cellFamily: cellFamily, member: "DataVGnd"L, vCompat: dataCell, hCompat: PLADataGnd]; PLADataTopGnd _ FindCell[ cellFamily: cellFamily, member: "DataTopGnd"L, hCompat: PLADataVGnd]; PLADataBottomGnd _ FindCell[ cellFamily: cellFamily, member: "DataBottomGnd"L, hCompat: PLADataVGnd]; PLADataRightGnd _ FindCell[ cellFamily: cellFamily, member: "DataRightGnd"L, vCompat: PLADataHGnd]; END; FindCell: PROCEDURE [ cellFamily: STRING, member: STRING, required: BOOLEAN _ FALSE, vCompat: Cell _ NIL, hCompat: Cell _ NIL] RETURNS [Cell] = BEGIN OPEN StringDefs; s: STRING _ [100]; s.length _ 0; AppendString[to: s, from: cellFamily]; AppendString[to: s, from: member]; FOR cp: LONG POINTER TO cList _ cellList, cp.nxt WHILE cp # NIL DO IF StringDefs.EquivalentString[cp.name, s] THEN BEGIN c: Cell _ cp.ob; IF vCompat # NIL THEN CheckPitchCompatability[c, vCompat, vertical]; IF hCompat # NIL THEN CheckPitchCompatability[c, hCompat, horizontal]; RETURN[c]; END; ENDLOOP; IF required THEN {Explain["Missing cell in family"L, s]; SIGNAL Punt}; RETURN[NIL]; END; FindDCell: PROCEDURE [ cellFamily, memberPrefix: STRING, required: BOOLEAN _ FALSE, vCompat: Cell _ NIL, hCompat: Cell _ NIL] RETURNS [d: DCell] = BEGIN OPEN StringDefs; originalLength: CARDINAL _ memberPrefix.length; member: STRING _ [50]; member.length _ 0; AppendString[to: member, from: memberPrefix]; AppendString[to: member, from: "0"L]; d[FALSE] _ FindCell[cellFamily, member, required, vCompat, hCompat]; member.length _ originalLength; AppendString[to: member, from: "1"L]; d[TRUE] _ FindCell[cellFamily, member, required, vCompat, hCompat]; IF vCompat # NIL OR hCompat # NIL THEN CheckPitchCompatability[d[FALSE], d[TRUE], diagonal]; END; -- of FindDCell FindDCellPr: PROCEDURE [ cellFamily, memberPrefix: STRING, required: BOOLEAN _ FALSE, vCompat: Cell _ NIL, hCompat: Cell _ NIL] RETURNS [p: DCellPr] = BEGIN OPEN StringDefs; originalLength: CARDINAL _ memberPrefix.length; member: STRING _ [50]; member.length _ 0; AppendString[to: member, from: memberPrefix]; AppendString[to: member, from: "0"L]; p[FALSE] _ FindDCell[cellFamily, member, required, vCompat, hCompat]; member.length _ originalLength; AppendString[to: member, from: "1"L]; p[TRUE] _ FindDCell[cellFamily, member, required, vCompat, hCompat]; IF vCompat # NIL OR hCompat # NIL THEN CheckPitchCompatability[p[FALSE][FALSE], p[TRUE][FALSE], diagonal]; END; -- of FindDCell CheckPitchCompatability: PROCEDURE [ c1, c2: Cell, dir: Direction, rep1: Point _ [1, 1], rep2: Point _ [1, 1]] = BEGIN OPEN StringDefs; FindCellName: PROCEDURE [c: Cell] RETURNS [STRING] = BEGIN FOR cp: LONG POINTER TO cList _ cellList, cp.nxt WHILE cp # NIL DO IF c = cp.ob THEN RETURN[cp.name] ENDLOOP; RETURN[""]; END; IF StepP[, c1, dir, rep1] # StepP[, c2, dir, rep2] THEN BEGIN cellNames: STRING _ [50]; cellNames.length _ 0; AppendString[to: cellNames, from: FindCellName[c1]]; AppendString[to: cellNames, from: " - "L]; AppendString[to: cellNames, from: FindCellName[c2]]; SELECT dir FROM vertical, up, down => Explain["Incompatible cell vertical pitches"L, cellNames]; horizontal, left, right => Explain["Incompatible cell horizontal pitches"L, cellNames]; ENDCASE => Explain["Incompatible cell sizes"L, cellNames]; -- SIGNAL Punt; END; END; -- of CheckPitchCompatability Replicate: PROCEDURE [c: Cell, p: Point, n: CARDINAL _ 1, dir: Direction _ down] RETURNS [Point] = BEGIN IF c = NIL THEN RETURN[p]; -- no cell FOR i: CARDINAL IN [0..n) DO SELECT dir FROM vertical, down, horizontal, right => BEGIN lpp _ insertList[lpp, makeList[c.p.anotherme[c], p.x, p.y, 0, 0]]; p _ StepP[p, c, dir]; END; left, up => BEGIN p _ StepP[p, c, dir]; lpp _ insertList[lpp, makeList[c.p.anotherme[c], p.x, p.y, 0, 0]]; END; ENDCASE => NULL; ENDLOOP; RETURN[p]; END; ReplicateEvenOdd: PROCEDURE [d: DCell, p: Point, n: CARDINAL, dir: Direction] RETURNS [Point] = BEGIN IF d[FALSE] = NIL AND d[TRUE] = NIL THEN RETURN[p]; -- no cells FOR i: CARDINAL IN [0..n) DO IF d[i MOD 2 = 0]#NIL THEN SELECT dir FROM vertical, down, horizontal, right => BEGIN lpp _ insertList[lpp, makeList[d[i MOD 2 = 0].p.anotherme[d[i MOD 2 = 0]], p.x, p.y, 0, 0]]; p _ StepP[p, d[i MOD 2 = 0], dir]; END; left, up => BEGIN p _ StepP[p, d[i MOD 2 = 0], dir]; lpp _ insertList[lpp, makeList[d[i MOD 2 = 0].p.anotherme[d[i MOD 2 = 0]], p.x, p.y, 0, 0]]; END; ENDCASE => NULL ELSE p _ StepP[p, d[NOT(i MOD 2 = 0)], dir]; ENDLOOP; RETURN[p]; END; StepP: PROCEDURE [ p: Point _ [0, 0], c: Cell, dir: Direction, rep: Point _ [1, 1]] RETURNS [Point] = BEGIN IF c = NIL THEN RETURN[p] ELSE SELECT dir FROM up => RETURN[[p.x, p.y - rep.y*c.size[1]]]; vertical, down => RETURN[[p.x, p.y + rep.y*c.size[1]]]; horizontal, right => RETURN[[p.x + rep.x*c.size[0], p.y]]; left => RETURN[[p.x - rep.x*c.size[0], p.y]]; upAndLeft => RETURN[[p.x - rep.x*c.size[0], p.y - rep.y*c.size[1]]]; upAndRight => RETURN[[p.x - rep.x*c.size[0], p.y + rep.y*c.size[1]]]; downAndLeft => RETURN[[p.x - rep.x*c.size[0], p.y + rep.y*c.size[1]]]; ENDCASE -- downAndRight, diagonal -- => RETURN[[p.x + rep.x*c.size[0], p.y + rep.y*c.size[1]]]; END; Half: PROCEDURE [x: CARDINAL] RETURNS [CARDINAL] = INLINE {RETURN[(x + 1)/2]}; MakeNewCell: PROCEDURE [name: STRING, lpp: LONG POINTER TO list] RETURNS [cp: LONG POINTER TO cList] = BEGIN min: Point _ [LAST[locNum], LAST[locNum]]; max: Point _ [FIRST[locNum], FIRST[locNum]]; FOR lp: LONG POINTER TO list _ lpp, lp.nxt WHILE lp # NIL DO ii: [0..1] _ IF InlineDefs.BITAND[lp.idx, 4] = 0 THEN 0 ELSE 1; min _ [MIN[min.x, lp.lx], MIN[min.y, lp.ly]]; max _ [ MAX[max.x, lp.lx + lp.ob.size[ii]], MAX[ max.y, lp.ly + lp.ob.size[ii + 1]]]; ENDLOOP; FOR lp: LONG POINTER TO list _ lpp, lp.nxt WHILE lp # NIL DO lp.lx _ lp.lx - min.x; lp.ly _ lp.ly - min.y; lp.selected _ FALSE; ENDLOOP; cp _ alocCList[]; cp.nxt _ cellList; cellList _ cp; cp.ob _ makeCell[max.x - min.x, max.y - min.y, 0, lpp]; cp.name _ name; END; -- of MakeNewCell DrawCell: PROCEDURE [obp: LONG POINTER TO object] = BEGIN lp: LONG POINTER TO list _ makeList[obp.p.anotherme[obp], xx, yy, 0, 0]; obp.returnable _ FALSE; masterList _ insertList[masterList, lp]; anyChanges _ sinceIOchanges _ TRUE; selNewThing[masterList, lp, TRUE]; putMark[xx, yy]; reDrawRect[getRect[lp], 0, TRUE, TRUE, FALSE]; END; -- of DrawCell Explain: PROCEDURE [why, explanation: STRING] = BEGIN IF explanation = NIL THEN explanation _ ""L; [] _ typeInC["Can't run PLAmaker [Confirm]"L, why, explanation] END; FixExtension: PROCEDURE [s, ext: STRING] RETURNS [se: STRING] = BEGIN FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN[s] ENDLOOP; se _ GetString[s.length + ext.length]; StringDefs.AppendString[to: se, from: s]; StringDefs.AppendString[to: se, from: ext]; FreeString[s]; END; RequestString: PROCEDURE[s1: STRING _ NIL, s2: STRING _ NIL, s3: STRING _ NIL] RETURNS[sResult: STRING] = BEGIN ok: BOOLEAN; [ok, sResult, ] _ typeIn[ IF s1#NIL THEN s1 ELSE ""L, IF s2#NIL THEN s2 ELSE ""L, IF s3#NIL THEN s3 ELSE ""L]; IF NOT ok THEN SIGNAL Punt; END; RequestInteger: PROCEDURE[s1: STRING _ NIL, s2: STRING _ NIL] RETURNS[INTEGER] = BEGIN DO s: STRING _ RequestString[s1, s2]; n: INTEGER _ StringDefs.StringToDecimal[s: s ! StringDefs.InvalidNumber => {FreeString[s]; LOOP}]; FreeString[s]; RETURN[n]; ENDLOOP; END; laydownTop: PROCEDURE [p: Point _ [0, 0]] RETURNS [hp: Point] = BEGIN OrB, k: CARDINAL; flag: BOOLEAN _ TRUE; -- place the top left corner cell, leave mark at bottom right corner hp _ StepP[StepP[p, PLADecoderDataTop, down], PLADecoderTopLeftCorner, up]; hp _ Replicate[PLADecoderTopLeftCorner, hp, 1, right]; hp _ StepP[hp, PLADecoderTopLeftCorner, down]; -- place the decoder cells, leave mark at bottom right corner FOR k IN [0..inCount) DO flag _ inputList[k].TopBottom=bottom; hp _ StepP[hp, PLADecoderTop[flag], up]; hp _ Replicate[PLADecoderTop[flag], hp, 1, right]; hp _ StepP[hp, PLADecoderTop[flag], down]; ENDLOOP; -- place the interface cell between the AND and OR planes hp _ StepP[hp, PLADecoderDataTop, up]; hp _ Replicate[PLADecoderDataTop, hp, 1, right]; hp _ StepP[hp, PLADecoderDataTop, down]; -- place the data cells, leave mark at bottom right corner OrB _ 0; FOR k IN [0..outCount) DO flag _ outputList[k].TopBottom=bottom; hp _ StepP[hp, PLADataTop[flag], up]; hp _ Replicate[PLADataTop[flag], hp, 1, right]; hp _ StepP[hp, PLADataTop[flag], down]; OrB _ OrB + 1; IF (OrB = boistCount) AND (outCount - k) > minBoistSpace THEN BEGIN OrB _ 0; hp _ StepP[hp, PLADataTopGnd, up]; hp _ Replicate[PLADataTopGnd, hp, 1, right]; hp _ StepP[hp, PLADataTopGnd, down]; END; ENDLOOP; -- place top right corner cell, leave mark at left bottom of row hp _ StepP[hp, PLADataTopRightCorner, up]; hp _ Replicate[PLADataTopRightCorner, hp, 1, right]; hp _ StepP[p, PLADecoderDataTop, down]; END; laydownBody: PROCEDURE [p: Point _ [0, 0]] RETURNS [hp: Point] = BEGIN i, j, k: CARDINAL _ 0; AndB, OrB: CARDINAL _ 0; PT, PT0, PT1: PTermLink; flag: BOOLEAN _ TRUE; FOR i IN hashIndex DO FOR PT _ hashPTerm[i], PT.next UNTIL PT=NIL DO hp _ p; j _ j + 1; -- laydown the Decoder Pullup hp _ Replicate[PLADecoderLeft[flag], hp, 1, right]; -- laydown the product term inputs FOR k IN [0..inCount) DO SELECT PT.input.term[k] FROM Assert => hp _ Replicate[PLADecoder[TRUE][FALSE], hp, 1, right]; Invert => hp _ Replicate[PLADecoder[FALSE][TRUE], hp, 1, right]; Absent => hp _ Replicate[PLADecoder[FALSE][FALSE], hp, 1, right]; ENDCASE; ENDLOOP; IF flag THEN PT0 _ PT ELSE PT1 _ PT; -- laydown the OR plane in pairs flag _ NOT flag; IF flag THEN BEGIN -- laydown the interface block hp _ StepP[hp, PLADecoder[FALSE][FALSE], up]; hp _ Replicate[PLADecoderData, hp, 1, right]; -- laydown the outputs that the product term drives OrB _ 0; FOR k IN [0..outCount) DO hp _ Replicate[PLAData[PT1.output.term[k]=Assert] [PT0.output.term[k]=Assert], hp, 1, right]; OrB _ OrB + 1; IF OrB = boistCount AND (outCount-k) > minBoistSpace THEN BEGIN hp _ Replicate[PLADataVGnd, hp, 1, right]; OrB _ 0; END; ENDLOOP; -- laydown the right end cell hp _ Replicate[PLADataRight, hp, 1, right]; END; -- Step down to the new layer p _ StepP[p, PLADecoder[FALSE][FALSE], down]; -- laydown the boister strip every boistCount layers AndB _ AndB + 1; IF AndB = boistCount AND (PTermCount - j) > minBoistSpace THEN BEGIN AndB _ 0; hp _ Replicate[PLADecoderLeftGnd, p, 1, right]; FOR k IN [0 .. inCount) DO hp _ Replicate[PLADecoderGnd, hp, 1, right]; ENDLOOP; hp _ Replicate[PLADecoderDataGnd, hp, 1, right]; OrB _ 0; FOR k IN [0..outCount) DO hp _ Replicate[PLADataHGnd, hp, 1, right]; OrB _ OrB + 1; IF (OrB = boistCount) AND (outCount-k) > minBoistSpace THEN BEGIN hp _ Replicate[PLADataGnd, hp, 1, right]; OrB _ 0; END; ENDLOOP; hp _ Replicate[PLADataRightGnd, hp, 1, right]; p _ StepP[p, PLADecoderLeftGnd, down]; END; ENDLOOP; ENDLOOP; -- check for odd number of product terms and finish layout -- if necessary IF NOT flag THEN BEGIN -- laydown a NULL AND term row hp _ p; hp _ Replicate[PLADecoderLeft[flag], hp, 1, right]; hp _ Replicate[PLADecoder[FALSE][FALSE], hp, inCount, right]; -- laydown the interface block hp _ StepP[hp, PLADecoder[FALSE][FALSE], up]; hp _ Replicate[PLADecoderData, hp, 1, right]; -- laydown the outputs that the product term drives OrB _ 0; FOR k IN [0..outCount) DO hp _ Replicate[PLAData[FALSE] [PT0.output.term[k]=Assert], hp, 1, right]; OrB _ OrB + 1; IF OrB = boistCount AND (outCount-k) > minBoistSpace THEN BEGIN hp _ Replicate[PLADataVGnd, hp, 1, right]; OrB _ 0; END; ENDLOOP; -- laydown the right end cell hp _ Replicate[PLADataRight, hp, 1, right]; -- Step down to the new layer p _ StepP[p, PLADecoder[FALSE][FALSE], down]; END; hp _ p; END; laydownBottom: PROCEDURE [p: Point _ [0, 0]] RETURNS [hp: Point] = BEGIN OrB, k: CARDINAL _ 0; flag: BOOLEAN _ TRUE; hp _ p; hp _ Replicate[PLADecoderBottomLeftCorner, hp, 1, right]; FOR k IN [0..inCount) DO flag _ inputList[k].TopBottom=bottom; hp _ Replicate[PLADecoderBottom[flag], hp, 1, right]; ENDLOOP; hp _ Replicate[PLADecoderDataBottom, hp, 1, right]; FOR k IN [0..outCount) DO flag _ outputList[k].TopBottom=bottom; hp _ Replicate[PLAOutMux[flag], hp, 1, right]; OrB _ OrB + 1; IF OrB = boistCount AND (outCount-k) > minBoistSpace THEN BEGIN hp _ Replicate[PLADataBottomGnd, hp, 1, right]; OrB _ 0; END; ENDLOOP; hp _ Replicate[PLADataBottomRightCorner, hp, 1, right]; END; ok: BOOLEAN; --bodyHeight, decoderDataX, dataX, dataRightX: locNum; --curPt: Point; --decoderWidth, wordsPerDataRow, wordCount, wordWidth: CARDINAL; --logWordsPerDataRow: INTEGER; fileName, memName, cellFamily, PLAName, wdPerRowStr: STRING _ NIL; s: StreamDefs.StreamHandle _ NIL; lpp: LONG POINTER TO list _ NIL; -- list of cells already placed -- M a i n B o d y BEGIN ENABLE Punt => GOTO Exit; -- for exits [ok, fileName, ] _ typeIn[""L, "Data file:"L, ".slim format"L]; IF NOT ok THEN GOTO Exit; fileName _ FixExtension[fileName, ".slim"L]; s _ StreamDefs.NewByteStream[ fileName, StreamDefs.Read ! SegmentDefs.FileNameError => { Explain["Can't find .slim file"L, name]; GOTO Exit}]; [ok, cellFamily, ] _ typeIn["Cell family:"L, ""L, ""L]; IF NOT ok THEN GOTO Exit; [ok, PLAName, ] _ typeIn["Name of completed PLA cell:"L, ""L, ""L]; IF NOT ok THEN GOTO Exit; FindPLACells[cellFamily]; -- Build the PLA's Product Term Matrix BuildProductTerms[s]; -- Construct the PLA symbol BEGIN flag: BOOLEAN _ TRUE; p, hp: Point; p _ hp _ [0, 0]; boistCount _ RequestInteger["Number of Min Terms between GND Lines:"L]; minBoistSpace _ RequestInteger["Minimum number of Min Terms between GND lines"L]; -- laydown the top of the PLA p _ laydownTop[p]; -- laydown the body of the PLA p _ laydownBody[p]; -- laydown the bottom of the PLA p _ laydownBottom[p]; END; DrawCell[MakeNewCell[PLAName, lpp].ob]; PLAName _ NIL; -- we gave the name to the cell --wordsPerDataRow _ 1; logWordsPerDataRow _ 0; --IF PLAOutMux[FALSE]#NIL THEN -- BEGIN -- t: CARDINAL; -- [ok, wdPerRowStr, ] _ typeIn[""L, "Words per row:"L, "(power of 2)"L]; -- IF NOT ok THEN GOTO Exit; -- t _ StringDefs.StringToNumber[s: wdPerRowStr, radix: 10]; -- FOR wordsPerDataRow _ 1, 2*wordsPerDataRow WHILE wordsPerDataRow NULL; END; -- give back all the storage we allocated --FreeBlocks[]; Z _ ZoneAllocDefs.DestroyAnXMZone[Z]; IF fileName # NIL THEN FreeString[fileName]; IF memName # NIL THEN FreeString[memName]; IF cellFamily # NIL THEN FreeString[cellFamily]; IF PLAName # NIL THEN FreeString[PLAName]; IF wdPerRowStr # NIL THEN FreeString[wdPerRowStr]; IF s # NIL THEN s.destroy[s]; anyChanges _ sinceIOchanges _ TRUE; END. -- of PLAMakerImpl