<> <> <> <> 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: BOOL _ TRUE; x: REF _ NIL; 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.ROPE _ NIL ] = { 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: ATOM _ CD.LayerKey[list.first]; [] _ SymTab.Insert[layerTable, Atom.GetPName[a], a]; ENDLOOP; }; END.