CDSimpleRulesImpl.mesa (part of ChipNDale)
Copyright © 1985 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, July 5, 1985 4:58:37 pm PDT
Last edited by: Christian Jacobi, December 15, 1986 12:03:50 pm PST
DIRECTORY
Atom, CD, CDOps, CDRects, CDSimpleRules, CDValue, Rope, SymTab;
CDSimpleRulesImpl: CEDAR PROGRAM    
IMPORTS Atom, CD, CDOps, CDRects, CDValue, Rope, SymTab
EXPORTS CDSimpleRules =
BEGIN
TechRec: TYPE = RECORD [
minWidth: PROC [layer: CD.Layer] RETURNS [CD.Number] ← NIL,
minDist: PROC [l1, l2: CD.Layer] RETURNS [CD.Number] ← NIL,
maxWidth: PROC [layer: CD.Layer] RETURNS [CD.Number] ← NIL,
contact: PROC [l1, l2: CD.Layer] RETURNS [CD.Object] ← NIL,
largeContact: PROC [design: CD.Design, size: CD.Position, l1, l2: CD.Layer] RETURNS [CD.Object] ← NIL,
layerTable: SymTab.Ref ← NIL
];
NotKnown: PUBLIC ERROR = CODE;
techNames: SymTab.Ref ← SymTab.Create[case: FALSE];
LToTech: PROC [layer: CD.Layer] RETURNS [tech: CD.Technology] = {
tech ← CD.LayerTechnology[layer ! CD.Error => GOTO bad];
IF tech=NIL THEN ERROR NotKnown;
EXITS bad => ERROR NotKnown;
};
TToRep: PROC [tech: CD.Technology] RETURNS [REF TechRec] = {
WITH CDValue.Fetch[boundTo: tech, key: techNames, propagation: technology] SELECT FROM
tr: REF TechRec => RETURN [tr];
ENDCASE => ERROR NotKnown;
};
MinWidth: PUBLIC PROC [layer: CD.Layer] RETURNS [CD.Number] = {
tr: REF TechRec ← TToRep[LToTech[layer]];
RETURN [
IF tr.minWidth=NIL THEN 0
ELSE tr.minWidth[layer]
]
};
MaxWidth: PUBLIC PROC [layer: CD.Layer] RETURNS [CD.Number] = {
tr: REF TechRec ← TToRep[LToTech[layer]];
RETURN [
IF tr.maxWidth=NIL THEN LAST[CD.Number]
ELSE tr.maxWidth[layer]
]
};
MinDist: PUBLIC PROC [l1, l2: CD.Layer] RETURNS [CD.Number] = {
tech: CD.Technology ← LToTech[l1];
tr: REF TechRec ← TToRep[tech];
IF tech#LToTech[l2] THEN ERROR;
RETURN [
IF tr.minDist=NIL THEN 0
ELSE tr.minDist[l1, l2]
]
};
GetLayer: PUBLIC PROC [technology, layer: REF] RETURNS [CD.Layer] = {
AToLayer: PROC [a: ATOM] = {
ok ← TRUE;
lay ← CD.FetchLayer[tech, a ! CD.Error => {ok ← FALSE; CONTINUE}];
IF lay=CD.errorLayer AND a#$errorLayer THEN ok ← FALSE;
};
lay: CD.Layer;
ok: BOOLTRUE;
x: REFNIL;
tr: REF TechRec;
tech: CD.Technology ← GetTechnology[technology];
IF tech=NIL THEN ERROR NotKnown;
WITH layer SELECT FROM
a: ATOM => {
AToLayer[a];
IF ok THEN RETURN [lay]
};
ri: REF INT => RETURN [ri^];
rl: REF CD.Layer => RETURN [rl^];
ENDCASE => NULL;
tr ← TToRep[tech];
IF tr.layerTable#NIL THEN
x ← SymTab.Fetch[tr.layerTable, CDOps.ToRope[layer]].val;
IF x#NIL AND x#layer THEN RETURN [GetLayer[tech, x]];
ERROR NotKnown
};
Rect: PUBLIC PROC [size: CD.Position, layer: CD.Layer] RETURNS [CD.Object] = {
RETURN [CDRects.CreateRect[size, layer]]
};
Contact: PUBLIC PROC [l1, l2: CD.Layer] RETURNS [CD.Object] = {
tech: CD.Technology ← LToTech[l1];
tr: REF TechRec ← TToRep[tech];
IF tech#LToTech[l2] THEN ERROR;
RETURN [
IF tr.contact=NIL THEN NIL
ELSE tr.contact[l1, l2]
]
};
LargeContact: PUBLIC PROC [design: CD.Design, size: CD.Position, l1, l2: CD.Layer] RETURNS [CD.Object] = {
tech: CD.Technology ← LToTech[l1];
tr: REF TechRec ← TToRep[tech];
IF tech#LToTech[l2] THEN ERROR;
IF design#NIL AND design.technology#LToTech[l2] THEN ERROR;
RETURN [
IF tr.largeContact=NIL THEN NIL
ELSE tr.largeContact[design, size, l1, l2]
]
};
GetTechnology: PUBLIC PROC [hint: REF] RETURNS [t: CD.Technology←NIL] = {
AToTech: PROC [a: ATOM] = {
t ← CD.FetchTechnology[a ! CD.Error => GOTO bad];
EXITS bad => t ← NIL;
};
GetWithRope: PROC [name: Rope.ROPE] RETURNS [t: CD.Technology←NIL] = {
EachTechnology: CD.TechnologyEnumerator = {
IF Rope.Equal[tech.name, name, FALSE]
OR Rope.Equal[Atom.GetPName[tech.key], name, FALSE]
THEN {quit ← TRUE; t ← tech}
};
IF Rope.IsEmpty[name] THEN RETURN;
WITH SymTab.Fetch[techNames, name].val SELECT FROM
tech: CD.Technology => RETURN [tech];
ENDCASE => NULL;
IF t=NIL THEN [] ← CD.EnumerateTechnologies[EachTechnology];
IF t=NIL THEN t ← CD.FetchTechnology[Atom.MakeAtom[name] ! CD.Error => CONTINUE];
};
WITH hint SELECT FROM
tech: CD.Technology => RETURN [tech];
d: CD.Design => RETURN [d.technology];
a: ATOM => AToTech[a];
r: Rope.ROPE => RETURN [GetWithRope[r]];
ENDCASE => NULL;
IF t=NIL AND hint#NIL THEN
RETURN [GetWithRope[CDOps.ToRope[hint]]];
};
ImplementTechnology: PUBLIC PROC [technology: CD.Technology,
minWidth: PROC [layer: CD.Layer] RETURNS [CD.Number],
minDist: PROC [l1, l2: CD.Layer] RETURNS [CD.Number],
maxWidth: PROC [layer: CD.Layer] RETURNS [CD.Number],
contact: PROC [l1, l2: CD.Layer] RETURNS [CD.Object],
largeContact: PROC [design: CD.Design, size: CD.Position, l1, l2: CD.Layer] RETURNS [CD.Object]←NIL,
layerTable: SymTab.Ref←NIL,
technologyNames: LIST OF Rope.ROPENIL
] = {
tr: REF TechRec;
IF technology=NIL THEN ERROR;
WITH CDValue.Fetch[technology, techNames, technology] SELECT FROM
trc: REF TechRec => tr ← trc;
ENDCASE => CDValue.Store[technology, techNames, tr←NEW[TechRec]];
IF minWidth#NIL THEN tr.minWidth ← minWidth;
IF minDist#NIL THEN tr.minDist ← minDist;
IF maxWidth#NIL THEN tr.maxWidth ← maxWidth;
IF contact#NIL THEN tr.contact ← contact;
IF largeContact#NIL THEN tr.largeContact ← largeContact;
IF layerTable#NIL THEN tr.layerTable ← layerTable;
FOR list: LIST OF Rope.ROPE ← technologyNames, list.rest WHILE list#NIL DO
[] ← SymTab.Insert[techNames, list.first, technology];
ENDLOOP;
[] ← SymTab.Insert[techNames, Atom.GetPName[technology.key], technology];
[] ← SymTab.Insert[techNames, technology.name, technology];
FOR list: LIST OF CD.Layer ← technology.usedLayers, list.rest WHILE list#NIL DO
a: ATOMCD.LayerKey[list.first];
[] ← SymTab.Insert[layerTable, Atom.GetPName[a], a];
ENDLOOP;
};
END.