-- 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