DIRECTORY CD, CDDirectory, CDFrame, IO, IFUPW, IFUPWControl, REFBit, PW, PWPins, Rope; IFUPWContDrive: CEDAR PROGRAM IMPORTS CDDirectory, CDFrame, IFUPW, IO, PW, PWPins, REFBit, Rope EXPORTS IFUPWControl = BEGIN OPEN IFUPWControl, CDF: CDFrame; driverTilesDesign: CD.Design; tileBuffer: REF DrTileRec _ NIL; DrTileRec: TYPE = RECORD[nconn: DrTileNonConn, conn: DrTileConn]; DrTileNonConn: TYPE = ARRAY PLAType OF ARRAY RowType OF CD.Object; DrTileConn: TYPE = ARRAY Dir OF REF DrTileArray; DrTileArray: TYPE = ARRAY DriveTileType OF CD.Object; DriveTileType: TYPE = {inPos, inNeg, latchA, latchB, gateP, gateN, gateA, gateB, latch, posSing, negSing, posDual, negDual}; GetDriverTiles: PROC RETURNS[tiles: REF DrTileRec] = { tDesign: CD.Design; IF tileBuffer#NIL THEN RETURN[tileBuffer]; log.PutRope["\n Initialize control driver tiles"]; tDesign _ driverTilesDesign_ PW.OpenDesign["IFUPWControl.dale"]; IF tDesign=NIL THEN ERROR PW.Error[MissingDesign, "TileSet design not found or empty"]; tiles _ tileBuffer _ NEW[DrTileRec]; tiles.conn[in] _ NEW[DrTileArray]; tiles.conn[out] _ NEW[DrTileArray]; tiles.nconn [precharged][header] _ PW.Get[design: tDesign, name: "DrHead" ]; tiles.nconn [precharged][xheader] _ PW.Get[design: tDesign, name: "DrXHead" ]; tiles.nconn [precharged][extend] _ PW.Get[design: tDesign, name: "DrExtend" ]; tiles.nconn [precharged][blank] _ PW.Get[design: tDesign, name: "DrBlank" ]; tiles.nconn [precharged][dataUp] _ tiles.nconn [precharged][blank]; tiles.nconn [precharged][dataDn] _ tiles.nconn [precharged][blank]; tiles.nconn [precharged][footer] _ PW.FlipY[tDesign, tiles.nconn [precharged][header]]; tiles.nconn [precharged][xfooter] _ PW.FlipY[tDesign, tiles.nconn [precharged][xheader]]; tiles.nconn [static][header] _ PW.Get[design: tDesign, name: "SPlaDrHead" ]; tiles.nconn [static][xheader] _ PW.Get[design: tDesign, name: "DrXHead" ]; tiles.nconn [static][extend] _ PW.Get[design: tDesign, name: "DrExtend" ]; tiles.nconn [static][blank] _ PW.Get[design: tDesign, name: "SPlaDrBlank24" ]; tiles.nconn [static][dataUp] _ tiles.nconn [static][blank]; tiles.nconn [static][dataDn] _ tiles.nconn [static][blank]; tiles.nconn [static][footer] _ PW.FlipY[tDesign, tiles.nconn [static][header]]; tiles.nconn [static][xfooter] _ PW.FlipY[tDesign, tiles.nconn [static][xheader]]; tiles.nconn [decoder][blank] _ PW.Get[design: tDesign, name: "DPlaDrBlank6" ]; --1 use tiles.conn [in][inPos] _ PW.Get[design: tDesign, name: "DrInInPos" ]; tiles.conn [in][inNeg] _ PW.Get[design: tDesign, name: "DrInInNeg" ]; tiles.conn [in][latchA] _ PW.Get[design: tDesign, name: "DrInA" ]; tiles.conn [in][latchB] _ PW.Get[design: tDesign, name: "DrInB" ]; tiles.conn [in][latch] _ PW.Get[design: tDesign, name: "DrLatch" ]; tiles.conn [in][posSing] _ PW.Get[design: tDesign, name: "DrInPosSing" ]; tiles.conn [in][negSing] _ PW.Get[design: tDesign, name: "DrInNegSing" ]; tiles.conn [in][posDual] _ PW.Get[design: tDesign, name: "DrInPosDual" ]; tiles.conn [in][negDual] _ PW.Get[design: tDesign, name: "DrInNegDual" ]; tiles.conn [out][inPos] _ PW.Get[design: tDesign, name: "DrOutInPos" ]; tiles.conn [out][inNeg] _ PW.Get[design: tDesign, name: "DrOutInNeg" ]; tiles.conn [out][latchA] _ PW.Get[design: tDesign, name: "DrOutLatchA" ]; tiles.conn [out][latchB] _ PW.Get[design: tDesign, name: "DrOutLatchB" ]; tiles.conn [out][latch] _ PW.Get[design: tDesign, name: "DrLatch" ]; tiles.conn [out][gateP] _ PW.Get[design: tDesign, name: "DrOutPos" ]; tiles.conn [out][gateN] _ PW.Get[design: tDesign, name: "DrOutNeg" ]; tiles.conn [out][gateA] _ PW.Get[design: tDesign, name: "DrOutAc" ]; tiles.conn [out][gateB] _ PW.Get[design: tDesign, name: "DrOutBc" ]; tiles.conn [out][posSing] _ PW.Get[design: tDesign, name: "DrOutPosSing" ]; tiles.conn [out][negSing] _ PW.Get[design: tDesign, name: "DrOutNegSing" ]; tiles.conn [out][posDual] _ PW.Get[design: tDesign, name: "DrOutPosDual" ]; tiles.conn [out][negDual] _ PW.Get[design: tDesign, name: "DrOutNegDual" ]; RETURN[tiles]}; RefToDriverFrame: PUBLIC PROC[ name: ROPE, xory: CDF.XorY, data, refRec: REF, unordered: BOOL, initial: DriveRec] RETURNS[frame: Frame]= { index: INT _ 0; desc: REFBit.REFBitDesc _ REFBit.Desc[refRec]; frame _ CDF.NewFrame [desc.fieldForm.size, xory, name.Cat["Core"], data, unordered]; FOR field: INT IN [0..desc.fieldForm.size) DO frame[field] _ CDF.NewFrame[ size: desc.fieldForm[field].bitSize, xory: xory, name: BitNameToSigName[desc.fieldForm[field].name], unord: unordered]; FOR bit: INT IN [0..desc.fieldForm[field].bitSize) DO rec: REF DriveRec _ NEW[DriveRec _ initial ]; frame[field][bit] _ CDF.NewFrame [size: 0, xory: xory, name: desc.bitForm[index].name, data:NIL, unord: unordered]; rec.name _ BitNameToSigName[desc.bitForm[index].name]; rec.nameInv _ BitNameToSigName[desc.bitForm[index].nameInv]; frame[field][bit].shell.name _ IF rec.name#NIL THEN rec.name ELSE rec.nameInv; frame[field][bit].data _ rec; index _ index + 1; ENDLOOP ENDLOOP; frame _ IFUPW.NFS[name, y, LIST[ CDF.NewObjectFrame[DriverCell[static, xheader]], frame, CDF.NewObjectFrame[DriverCell[static, xfooter]] ] ] }; DrRope: PROC[rec: REF DriveRec] RETURNS[rope: ROPE] = { dirRope: ARRAY Dir OF ROPE = [" in", "out"]; polRope: ARRAY Polarity OF ROPE = ["pos", "neg", "unk"]; phRope: ARRAY Ph OF ROPE = ["A ", "B ", "AB ", "BA ", "Ac ", "Bc ", "unk"]; gateRope: ARRAY DrGate OF ROPE = [" neg", "negAc", "negBc", " pos"]; dualSing: ARRAY BOOL OF ROPE = ["sing", "dual"]; rope _ IO.PutFR["%3g %12g %12g", IO.rope[dirRope[rec.drDir]], IO.rope[rec.name], IO.rope[rec.nameInv] ]; rope _ rope.Cat[IO.PutFR[" %g%g %g%g", IO.rope[polRope [rec.in.pol]], IO.rope[phRope [rec.in.ph]], IO.rope[polRope [rec.ref.pol]], IO.rope[phRope [rec.ref.ph]] ] ]; rope _ rope.Cat[IO.PutFR[" %g %g %g%g", IO.rope[gateRope [rec.gate]], IO.rope[dualSing [rec.dualOut]], IO.rope[polRope [rec.out.pol]], IO.rope[phRope [rec.out.ph]] ] ] }; ListDrivers: PROC[drives: Frame, list: IO.STREAM _ IO.noWhereStream] = { ListDrive: CDF.EnumProc = {list.PutF["Driver: %g", IO.rope[DrRope[NARROW[frame.data]]]]}; IF list=IO.noWhereStream THEN {list _ log}; CDF.EnumFrameBotOnly[drives, ListDrive]}; AccmPosAndAddDriversBasedOnShellSide: PUBLIC PROC [drivers: Frame, shell: REF CDF.ShellRec, side: Side] RETURNS[Frame]= { AddPin: PROC[frame: Frame] RETURNS[new, dFrame: Frame_NIL, found: BOOL, pos: INT] = { new _ frame; IF frame.seqSize#0 THEN { FOR index: INT IN [0..frame.seqSize) DO [frame[index], dFrame, found, pos] _ AddPin[frame[index]]; IF NOT found THEN LOOP; IncrAvePos[frame, pos]; IF dFrame=NIL THEN RETURN[frame, NIL, found, pos] ELSE { new _ CDF.NewFrame [frame.seqSize+1, frame.xory, frame.shell.name, frame.data, frame.unordered]; new.shell.size _ frame.shell.size; FOR index: INT IN [0..frame.seqSize) DO new[index] _ frame[index] ENDLOOP; new[frame.seqSize] _ dFrame; RETURN[new, NIL, TRUE, pos]}; ENDLOOP } ELSE { rec: REF DriveRec; posMatch, negMatch: BOOL; IF frame.data=NIL OR NOT ISTYPE[frame.data, REF DriveRec] THEN RETURN[frame, NIL, FALSE, 0]; rec _ NARROW[frame.data]; posMatch _ Rope.Equal[root, rec.name, FALSE]; negMatch _ Rope.Equal[root, rec.nameInv, FALSE]; IF NOT posMatch AND NOT negMatch THEN RETURN[frame, NIL, FALSE, 0]; IF posMatch AND negMatch THEN { log.PutF["\n ERROR: PIN %g matches both %g and %g", IO.rope[pin.name], IO.rope[rec.name], IO.rope[rec.nameInv]]; RETURN[frame, NIL, FALSE, 0]}; IF rec.name#NIL AND rec.nameInv#NIL AND not THEN { log.PutF["\n ERROR: PIN %g implicitly matches %g", IO.rope[pin.name], IO.rope[IF posMatch THEN rec.name ELSE rec.nameInv]]; RETURN[frame, NIL, FALSE, 0]}; pos _ CDF.GetSidePos[pin]; IF rec.drDir=in AND rec.in.ph#unk AND rec.in.ph#ph OR rec.drDir=out AND rec.out.ph#unk AND rec.out.ph#ph THEN { dFrame _ CDF.NewFrame [0, frame.xory, frame.shell.name.Cat["-alt"], ,frame.unordered]; IncrAvePos[dFrame, pos]; dFrame.data _ rec _ NEW[DriveRec _ rec^]; IF rec.drDir=out THEN rec.out _ [ ] ELSE rec.in _ [ ]} ELSE {dFrame _ NIL; IncrAvePos[frame, pos]}; IF rec.drDir=in THEN { IF posMatch#not THEN rec.in.pol _ pos ELSE rec.in.pol _ neg; rec.in.ph _ ph} ELSE { SELECT rec.out.pol FROM pos => IF posMatch=not THEN rec.dualOut _ TRUE; neg => IF posMatch#not THEN rec.dualOut _ TRUE; ENDCASE => rec.out.pol _ IF posMatch#not THEN pos ELSE neg; rec.out.ph _ ph}; RETURN[frame, dFrame, TRUE, pos]} }; pin: REF CDF.PinRec; not: BOOL; root: ROPE; ph: Ph; FOR pinIndex: INT IN [0..shell.pins[side].seqSize) DO done: BOOL; pin _ shell.pins[side][pinIndex]; [not, root, ph] _ ParsePinName[pin.name]; [drivers, , done, ] _ AddPin[drivers]; IF NOT done THEN { IF Rope.Equal[root, "VDD"] THEN LOOP; IF Rope.Equal[root, "GND"] THEN LOOP; IF Rope.Equal[root, "PhA"] THEN LOOP; IF Rope.Equal[root, "PhB"] THEN LOOP; log.PutF["\n Orphan pin: %g", IO.rope[pin.name]]; } ENDLOOP; RETURN[drivers] }; GetAvePos: PROC[frame: Frame] RETURNS[INT] = { IF frame.shell.size.x=unk THEN RETURN[0]; RETURN[frame.shell.pos.x/frame.shell.size.x]}; IncrAvePos: PROC[frame: Frame, pos: INT] = { IF frame.shell.size.x=unk THEN frame.shell.size.x _ 0; IF frame.shell.pos.x=unk THEN frame.shell.pos _ [0,0]; frame.shell.size.x _ frame.shell.size.x + 1; frame.shell.pos.x _ frame.shell.pos.x + pos}; ListOrphanFrames: PROC[frame: Frame] = { LOF: CDF.EnumProc = {IF frame.shell.size.x<0 THEN log.PutF["\n Orphan frame: %g", IO.rope[frame.shell.name]]}; CDF.EnumFrameTopFirst[frame, LOF]}; ReorderFrameBasedOnAvePos: PUBLIC PROC[frame: Frame] = { -- shell.pos.x/shell.size.x found: BOOL _ TRUE; ListOrphanFrames[frame]; IF frame.unordered THEN WHILE found DO found _ FALSE; IF frame.seqSize>0 THEN FOR index: INT IN [0..frame.seqSize-1) DO IF GetAvePos[frame[index]] > GetAvePos[frame[index+1]] THEN { temp: Frame _ frame[index]; frame[index] _ frame[index+1]; frame[index+1] _ temp; found _ TRUE }; ENDLOOP ENDLOOP; FOR index: INT IN [0..frame.seqSize) DO ReorderFrameBasedOnAvePos[frame[index]] ENDLOOP}; BitNameToSigName: PUBLIC PROC [name: ROPE] RETURNS [ROPE] ~ { Cap: PROC[rope: ROPE, idx: INT] RETURNS[ROPE] = { char: CHAR _ rope.Fetch[idx+1]; IF char IN ['a..'z] THEN char _ char + LOOPHOLE['A - 'a]; RETURN[IO.PutFR["%g", IO.char[char]]]}; IF name = NIL THEN RETURN[NIL]; name _ Rope.Cat[Cap[name, -1], name.Substr[1]]; DO index: INT _ name.Index[0, "."]; IF index+1 >= name.Length[] OR name.Fetch[index+1] IN ['0..'9] THEN RETURN[name]; name _ Rope.Cat[name.Substr[0,index], Cap[name, index], name.Substr[index+2]]; ENDLOOP }; ParsePinName: PUBLIC PROC [name: ROPE] RETURNS [not: BOOL, root: ROPE, ph: Ph] ~ { phasesize: ARRAY Ph OF INT _ [1,1,2,2,2,2,0]; sufix: ROPE; end: INT; not4: BOOL _ Rope.Equal[name.Substr[0, 4], "Not.", FALSE]; not3: BOOL _ Rope.Equal[name.Substr[0, 3], "Not", FALSE]; name _ name.Substr[start: (IF not4 THEN 4 ELSE IF not3 THEN 3 ELSE 0)]; not _ not3 OR not4; end _ name.Index[0, "."]; root _ name.Substr[0, end]; sufix _ IF end< name.Length THEN name.Substr[end] ELSE NIL; ph _ SELECT name.Fetch[root.Length[]-1] FROM 'A => SELECT root.Fetch[root.Length[]-2] FROM 'B=> BA, ENDCASE => A, 'B => SELECT root.Fetch[root.Length[]-2] FROM 'A=> AB, ENDCASE => B, 'c => SELECT root.Fetch[root.Length[]-2] FROM 'A=> Ac, 'B=> Bc, ENDCASE => unk, ENDCASE => unk; root _ root.Substr[0, root.Length[]-phasesize[ph]]; root _ root.Cat[sufix] }; SignalName: PUBLIC PROC [not: BOOL, positive, negative: ROPE, ph: Ph] RETURNS [name: ROPE] ~ { PhRope: ARRAY Ph OF ROPE _ ["A", "B", "AB", "BA", "Ac", "Bc", ""]; altName, phRope: ROPE; end: INT; IF not THEN {name _ negative; altName _ positive} ELSE {name _ positive; altName _ negative}; phRope _ PhRope[ph]; IF name = NIL THEN name _ Rope.Cat["Not", altName]; end _ name.Index[0, "."]; name _ name.Substr[0, end].Cat[phRope, name.Substr[end]]}; DriverPinName: PUBLIC PROC[type: DriverPinType, driver: REF DriveRec] RETURNS [name: ROPE] = { RETURN[ SELECT type FROM in => SignalName[driver.in.pol = neg, driver.name, driver.nameInv, driver.in.ph], out0 => SignalName[driver.out.pol = neg, driver.name, driver.nameInv, driver.out.ph], out1 => IF ~driver.dualOut THEN NIL ELSE SignalName[ driver.out.pol # neg, driver.name, driver.nameInv, driver.out.ph] ENDCASE => ERROR]}; DriverFill: PUBLIC PROC RETURNS[frame: Frame] = { frame _ CDF.NewFrame[2, x, CDF.ID["DriverFill"]]; frame[0] _ CDF.Glue[]; frame[1] _ CDF.NewObjectFrame[DriverCell[static, extend]]}; DriverExt: PUBLIC PROC[up: BOOL _ FALSE] RETURNS[frame: Frame] = { frame _ CDF.NewFrame[2, x, CDF.ID["DriverFill"]]; frame[0] _ IF up THEN CDF.Glue[t:ext, b:conn] ELSE CDF.Glue[t:conn, b:ext]; frame[1] _ CDF.NewObjectFrame[DriverCell[static, extend]]}; DriverCell: PUBLIC PROC[ plaType: PLAType, drRowType: RowType, driver: REF DriveRec _ NIL, design: CD.Design _ NIL] RETURNS[cell: CD.Object] = { renameProc: PWPins.RenameProc ~ { -- newRope oldRope RETURN[ SELECT TRUE FROM Rope.Equal[oldRope, "in"] => DriverPinName[in, driver], Rope.Equal[oldRope, "out0"] => DriverPinName[out0, driver], Rope.Equal[oldRope, "out1"] => DriverPinName[out1, driver], ENDCASE => oldRope]}; drName: ROPE; found: BOOL; drTiles: REF DrTileRec _ GetDriverTiles[]; decoderOut: BOOL _ plaType=decoder AND drRowType=conn AND driver.drDir=out; IF plaType=decoder THEN plaType _ static; IF drRowType#conn THEN RETURN[drTiles.nconn[plaType][drRowType]]; drName _ GenDriverName[driver]; IF decoderOut THEN drName _ Rope.Cat["D", drName]; [found, cell] _ CDDirectory.Fetch[design, drName]; IF ~found THEN { list: PW.ListOb; tiles: REF DrTileArray _ drTiles.conn[driver.drDir]; list _ CONS[tiles[IF driver.ref.pol=driver.in.pol THEN inPos ELSE inNeg ], list]; list _ CONS[tiles[IF driver.ref.ph=A THEN latchA ELSE latchB ], list]; list _ CONS[tiles[latch], list]; list _ IF driver.drDir=in THEN list ELSE CONS[tiles[SELECT driver.gate FROM neg => gateN, negAc => gateA, negBc => gateB, pos => gateP, ENDCASE => ERROR], list]; list _ CONS[tiles[(IF (driver.ref.pol=driver.out.pol)=(driver.gate=pos) THEN (IF driver.dualOut THEN posDual ELSE posSing) ELSE (IF driver.dualOut THEN negDual ELSE negSing)) ], list]; IF driver.drDir=out THEN list _ PW.Reverse[list]; cell _ PW.AbutListX[design, list]; IF decoderOut THEN cell _ PW.AbutY[design, drTiles.nconn[decoder][blank], cell]; PW.RenameObject[design, cell, drName] }; cell _ PWPins.RenamePins[design, cell, renameProc]; PW.RenameObject[design, cell, SignalName [driver.out.pol=neg, driver.name, driver.nameInv, driver.out.ph]]}; BuildDrivers: PUBLIC PROC[frame: Frame, design: CD.Design] = { IF frame.seqSize > 0 THEN FOR index: INT IN [0..frame.seqSize) DO BuildDrivers[frame[index], design] ENDLOOP ELSE { driver: REF DriveRec _ NARROW[frame.data]; frame.data _ DriverCell[static, conn, driver, design]; frame.shell _ CDF.ShellFromObject[NARROW[frame.data]]} }; GenDriverName: PUBLIC PROC[driver: REF DriveRec] RETURNS[name: ROPE] = { name _ "Dr"; name _ name.Cat[IF driver.drDir = in THEN "In" ELSE "Out"]; name _ name.Cat[IF driver.ref.pol=driver.in.pol THEN "Pos" ELSE "Neg"]; name _ name.Cat[IF driver.ref.ph=A THEN "A" ELSE "B"]; name _ name.Cat[SELECT driver.gate FROM neg => "Neg", negAc => "NAc", negBc => "NAc", pos => "", ENDCASE => ERROR]; name _ name.Cat[ IF (driver.ref.pol=driver.out.pol)=(driver.gate=pos) THEN "Pos" ELSE "Neg"]; name _ name.Cat[IF driver.dualOut THEN "Dual" ELSE "Sing"]}; log: IO.STREAM _ CDF.GetLog[]; END. ÈIFUPWContDrive.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last Edited by Curry, January 28, 1986 4:49:41 pm PST uses frame.shell.size.x and pos.x for count and position Êö˜šœ™Jšœ<™šœ˜šœœœœ˜)Jšœ$˜-—šœ˜Jšœœ œ ˜*Jšœ6˜6Jšœœœ˜9———J˜š ž œœœ œ œœ˜HJšœ ˜ Jšœœœœ˜?Jšœœ œœ˜IJšœœœœ˜;šœœ ˜'Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœœ˜—šœ˜Jšœ4œœ˜M—Jšœœœœ ˜B—J˜Jšœœœœ ˜J˜Jšœ˜J˜—J˜—…—