-- ChipDRCImpl2.mesa -- last modified by E. McCreight, November 22, 1982 4:37 PM -- written by E. McCreight, April 14, 1982 10:25 AM DIRECTORY ChipDRC, ChipExpand, ChipNetDefs, ChipUserInt, CWF, ppdefs, ppdddefs, ppMainDefs, StreamDefs; ChipDRCImpl2: PROGRAM IMPORTS ChipExpand, ChipNetDefs, ChipUserInt, CWF, ppdddefs, ppdefs, ppMainDefs, StreamDefs EXPORTS ChipDRC = BEGIN OPEN StreamDefs, CWF, ppdefs, ChipUserInt, ChipNetDefs; holdViolations: PUBLIC BOOLEAN ← FALSE; violations: ViolationListPtr ← NIL; NoteViolation: PUBLIC PROCEDURE[v: Violation] = BEGIN IF NOT holdViolations THEN TellUserAboutViolation[v: v, tell: RemarkAtPoint]; violations ← uz.NEW[ViolationList ← [next: violations, v: v]]; END; -- of NoteViolations EnumerateViolations: PUBLIC PROCEDURE[] = BEGIN IF violations#NIL THEN BEGIN IF HeSaysYes[IF holdViolations THEN "There are design errors. Want to see them?"L ELSE "Want to see the design errors again?"L] THEN DO FOR vl: ViolationListPtr ← violations, vl.next WHILE vl#NIL DO TellUserAboutViolation[v: vl.v, tell: RemarkAtPoint ! Punt => GOTO NoMore]; REPEAT NoMore => NULL; ENDLOOP; IF NOT HeSaysYes[ "Want to see the design errors again?"L] THEN EXIT; ENDLOOP; IF HeSaysYes["Write design errors to a file?"L] THEN BEGIN ViolationToShowFile: PROCEDURE[p: Point, s: STRING] = BEGIN OPEN ppdddefs; cifX: LONG INTEGER ← LONG[(ppdddefs.pCifScale/Lambda)]*p.x; cifY: LONG INTEGER ← -LONG[(ppdddefs.pCifScale/Lambda)]*p.y; -- I have no idea why Chipmonk wants this y -- co-ordinate inverted! FWF3[showFile, "%ld %ld %s*n", @cifX, @cifY, s]; END; showFile: DiskHandle; name: STRING ← RequestString["Error file name?"L]; IF name=NIL OR name.length=0 THEN name ← newString[ppMainDefs.fileName]; name ← FixExtension[name, ".drc"]; showFile ← NewByteStream[name, WriteAppend]; FOR vl: ViolationListPtr ← violations, vl.next WHILE vl#NIL DO TellUserAboutViolation[v: vl.v, tell: ViolationToShowFile]; ENDLOOP; FreeString[name]; TruncateDiskStream[showFile]; END; END; END; -- of EnumerateViolations TellUserAboutViolation: PROCEDURE[v: Violation, tell: PROCEDURE[p: Point, s: STRING]] = BEGIN s: STRING ← [100]; SELECT v.type FROM tooNarrow => SWF1[s, "%s geometry too small here"L, levelNames[v.lev1]]; tooClose => IF v.lev1=v.lev2 THEN SWF1[s, "%s features are too close here."L, levelNames[v.lev1]] ELSE SWF2[s, "%s and %s features too close here."L, levelNames[v.lev1], levelNames[v.lev2]]; noNetToWell => SWF1[s, "%s is floating here."L, levelNames[v.lev1]]; differentNetsToWell => SWF1[s, "%s connects to two different nets."L, levelNames[v.lev1]]; terminalsUnconnected => BEGIN s2: STRING ← [100]; s2.length ← 0; AppendTerminalName[s: s2, c: v.caller]; SWF1[s, """%s"" terminals failed to connect."L, s2]; END; coverageNeeded => SWF1[s, "%s coverage needed here."L, levelNames[v.lev1]]; coverageForbidden => SWF1[s, "%s coverage is forbidden here."L, levelNames[v.lev1]]; bogusTransistor => SWF1[s, "Illegal Chipmonk %s transistor here."L, levelNames[v.lev1]]; cantCheck => SWF0[s, "Bug in extractor prevented some checking here"L]; ENDCASE => SWF0[s, "Unknown design error"L]; tell[p: v.place, s: s]; END; -- of TellUserAboutViolation CheckTerminalConnections: PUBLIC PROCEDURE[ call: CellCallPtr] = BEGIN ChipExpand.CheckClusters[call]; FOR cluster: ClusterPtr ← call.clusters, cluster.next WHILE cluster#NIL DO IF cluster.first.next#NIL THEN BEGIN NoteViolation[[ place: RefCoordPt[ItemInWorld[cluster.first.source]], caller: cluster.first.source, type: terminalsUnconnected]]; FOR mc: MustConnectPtr ← cluster.first.next, mc.next WHILE mc#NIL DO NoteViolation[[ place: RefCoordPt[ItemInWorld[mc.source]], caller: mc.source, type: terminalsUnconnected]]; ENDLOOP; END; ENDLOOP; FOR c: InstancePtr ← call.offspring, c.sibling WHILE c#NIL DO WITH dc: c SELECT FROM cell => CheckTerminalConnections[@dc]; ENDCASE => NULL; ENDLOOP; END; -- of CheckTerminalConnections PurgeDRCViolations: PUBLIC PROCEDURE[id: NetIdPtr] = BEGIN remaining, ncv: ConditionalViolationPtr ← NIL; cv: ConditionalViolationPtr; Reconsider: PROCEDURE[certain, stillPossible: BOOLEAN] = INLINE BEGIN IF certain THEN NoteViolation[cv.v]; IF certain OR NOT stillPossible THEN BEGIN -- remove from conditional violations IF cv.otherNet#NIL THEN cv.otherNet ← DeRefNet[cv.otherNet]; uz.FREE[@cv]; END ELSE {cv.next ← remaining; remaining ← cv}; END; WITH did: id SELECT FROM normal => BEGIN FOR cv ← id.violations, ncv WHILE cv#NIL DO ncv ← cv.next; SELECT cv.v.type FROM tooNarrow => Reconsider[certain: NOT did.couldBeLogo, stillPossible: currentX<=id.final.r.x2]; tooClose, coverageForbidden => BEGIN otherId: NormalNetIdPtr = GetNormalNetId[@cv.otherNet]; Reconsider[ certain: id#otherId AND NOT (did.couldBeLogo AND otherId.couldBeLogo) AND (otherId.final.r.x2<currentX OR id.final.r.x2<currentX), stillPossible: id#otherId AND (currentX<=otherId.final.r.x2 OR currentX<=id.final.r.x2)]; END; ENDCASE => ERROR; ENDLOOP; id.violations ← remaining; END; well => IF id.final.r.x2<currentX AND did.attachedTo=NIL THEN NoteViolation[[ place: RefCoordPt[id.final.r], type: noNetToWell, lev1: id.final.lev]]; ENDCASE => NULL; END; -- of PurgeDRCViolations END. -- of ChipDRCImpl2