<> <> <> <> DIRECTORY CD, CDAtomicObjects, CDSimpleRules, DABasics, Route, RoutePrivate, RouteTechnology; RouteTechnologyImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDSimpleRules, Route EXPORTS RouteTechnology = { <> GetWidth: PUBLIC PROC [layer: CD.Layer] RETURNS [CD.Number] = { RETURN[CDSimpleRules.MinWidth[NIL, layer]]}; GetSpacing: PUBLIC PROC [layer: CD.Layer] RETURNS [CD.Number] = { RETURN[CDSimpleRules.MinSpace[NIL, layer, layer]]}; ContactSize: PUBLIC PROC [contact: CD.Object] RETURNS [CD.Number] = { r: CD.Rect _ CD.InterestRect[contact]; RETURN[MAX[ABS[r.x2 - r.x1], ABS[r.y2 - r.y1]]]}; GetMaterialToContact: PUBLIC PROC [layer: CD.Layer, contact: CD.Object] RETURNS [dist: CD.Number] = { <> matToContact: CD.Number _ GetSpacing[layer] + ContactSize[contact]/2 + GetWidth[layer]/2; contactToContact: CD.Number _ GetSpacing[layer] + ContactSize[contact]; RETURN[MAX[matToContact, contactToContact]]}; <> LToTech: PUBLIC PROC [layer: CD.Layer] RETURNS [tech: CD.Technology] = { tech _ CD.LayerTechnology[layer ! CD.Error => GOTO bad]; IF tech=NIL THEN Route.Error[callingError, "Invalid layer"]; EXITS bad => Route.Error[callingError, "Invalid layer"]}; <> GetContact: PUBLIC PROC [layer1, layer2: CD.Layer] RETURNS [CD.Object] = { <<-- Create a big contact; may return the same object>> <<-- on multiple calls; the contact object should be considered>> <<-- to be read-only.>> RETURN[CDSimpleRules.Contact[NIL, layer1, layer2]]}; GetBigContact: PUBLIC PROC [size: DABasics.Position, layer1, layer2: CD.Layer] RETURNS [obj: CD.Object _ NIL] = { <<-- Create a big contact; may return NIL (if big contacts aren't defined>> <<-- may return the same object>> <<-- on multiple calls; the contact object should be considered>> <<-- to be read-only.>> l1a: ATOM _ CD.LayerKey[layer1]; l2a: ATOM _ CD.LayerKey[layer2]; tech: CD.Technology _ LToTech[layer1]; IF tech # LToTech[layer2] THEN Route.Error[callingError, "Invalid layers"]; SELECT tech.key FROM $cmos => NULL; $cmosB => { SELECT TRUE FROM (l1a = $met2 AND l2a = $met) OR (l1a = $met AND l2a = $met2) => obj _ CDAtomicObjects.CreateAtomicOb[$C2LargeVia, size, tech]; (l1a = $pol AND l2a = $met) => obj _CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer1]; (l1a = $met AND l2a = $pol) => obj _CDAtomicObjects.CreateAtomicOb[$C2LargeSimpleCon, size, tech, layer2]; ENDCASE => Route.Error[callingError, "Invalid layers"]}; ENDCASE => Route.Error[callingError, "Unsupported technology"]}; <> CmosDesignRules: PUBLIC PROC [designRuleParms: Route.DesignRulesParameters] RETURNS[designRules: Route.DesignRules _ NEW[Route.DesignRulesRec]] = { <> cndObj: CD.Object; designRules.trunkDirection _ designRuleParms.trunkDirection; designRules.branchDirection _ IF designRuleParms.trunkDirection = horizontal THEN vertical ELSE horizontal; designRules.trunkLayer _ IF designRuleParms.trunkDirection = horizontal THEN designRuleParms.horizLayer ELSE designRuleParms.vertLayer; designRules.branchLayer _ IF designRuleParms.trunkDirection = horizontal THEN designRuleParms.vertLayer ELSE designRuleParms.horizLayer; cndObj _ GetContact[designRules.trunkLayer, designRules.branchLayer]; designRules.branchWidth _ GetWidth[designRules.branchLayer]; designRules.branchSpacing _ GetSpacing[designRules.branchLayer]; designRules.branchToContact _ GetMaterialToContact[designRules.branchLayer, cndObj]; designRules.trunkToTrunk _ designRuleParms.trunkToTrunk; designRules.branchToBranch _ MAX[designRules.branchWidth + designRules.branchSpacing, designRules.branchToContact]; designRules.branchOffset _ designRules.branchSpacing; designRules.trunkWidth _ GetWidth[designRules.trunkLayer]; designRules.trunkSpacing _ GetSpacing[designRules.trunkLayer]; designRules.trunkToContact _ GetMaterialToContact[designRules.trunkLayer, cndObj]; designRules.trunkOffset _ designRules.trunkSpacing; designRules.contactSize _ ContactSize[cndObj]; designRules.contactToContact _ designRules.contactSize + MAX[designRules.trunkSpacing, designRules.branchSpacing]; designRules.pinSpacing _ designRuleParms.pinSpacing; designRules.trunkToEdge _ designRuleParms.trunkToEdge}; <<>> DesignRulesParameters: PUBLIC PROC [technology: CD.Technology, horizLayer, vertLayer: CD.Layer, trunkDirection: DABasics.Direction] RETURNS[designRuleParms: Route.DesignRulesParameters] = { <> trunkLayer: CD.Layer _ IF trunkDirection = horizontal THEN horizLayer ELSE vertLayer; branchLayer: CD.Layer _ IF trunkDirection = horizontal THEN vertLayer ELSE horizLayer; cndObj: CD.Object _ GetContact[trunkLayer, branchLayer]; contactToContact: DABasics.Number _ ContactSize[cndObj] + MAX[GetSpacing[trunkLayer], GetSpacing[branchLayer]]; trunkToTrunk: DABasics.Number _ MAX[GetWidth[trunkLayer] + GetSpacing[trunkLayer], GetMaterialToContact[trunkLayer, cndObj], contactToContact]; pinSpacing: DABasics.Number _ ContactSize[cndObj]/2 + GetWidth[branchLayer]/2 + GetWidth[branchLayer]; trunkToEdge: DABasics.Number _ MAX[GetSpacing[branchLayer], GetSpacing[trunkLayer]] + MAX[ContactSize[cndObj], GetWidth[trunkLayer]]/2; designRuleParms _ NEW[Route.DesignRulesParametersRec _ [technology: technology, horizLayer: horizLayer, vertLayer: vertLayer, trunkDirection: trunkDirection, trunkToTrunk: trunkToTrunk, pinSpacing: pinSpacing, trunkToEdge: trunkToEdge]]}; }.