<> <> <> <> DIRECTORY CD, CDAtomicObjects, CDSimpleRules, DABasics, DesignRules, Route, NewRouteTechnology; NewRouteTechnologyImpl: CEDAR PROGRAM IMPORTS CD, CDAtomicObjects, CDSimpleRules, DesignRules, Route EXPORTS NewRouteTechnology = { <> <> <> <> <> 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 [rules: DesignRules.Rules, layer: CD.Layer, contact: CD.Object] RETURNS [dist: CD.Number] = { <> matToContact: CD.Number _ DesignRules.MinSpace[rules, layer, layer].s + ContactSize[contact]/2 + DesignRules.MinWidth[rules, layer].w/2; contactToContact: CD.Number _ DesignRules.MinSpace[rules, layer, layer].s + 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 [rules: DesignRules.Rules, 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 _ DesignRules.MinWidth[rules, designRules.branchLayer].w; designRules.branchSpacing _ DesignRules.MinSpace[rules, designRules.branchLayer, designRules.branchLayer].s; designRules.branchToContact _ GetMaterialToContact[rules, designRules.branchLayer, cndObj]; designRules.trunkToTrunk _ designRuleParms.trunkToTrunk; designRules.branchToBranch _ MAX[designRules.branchWidth + designRules.branchSpacing, designRules.branchToContact]; designRules.branchOffset _ designRules.branchSpacing; designRules.trunkWidth _ DesignRules.MinWidth[rules, designRules.trunkLayer].w; designRules.trunkSpacing _ DesignRules.MinSpace[rules, designRules.trunkLayer, designRules.trunkLayer].s; designRules.trunkToContact _ GetMaterialToContact[rules, 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 [rules: DesignRules.Rules, 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[DesignRules.MinSpace[rules, trunkLayer, trunkLayer].s, DesignRules.MinSpace[rules, branchLayer, branchLayer].s]; trunkToTrunk: DABasics.Number _ MAX[DesignRules.MinWidth[rules, trunkLayer].w + DesignRules.MinSpace[rules, trunkLayer, trunkLayer].s, GetMaterialToContact[rules, trunkLayer, cndObj], contactToContact]; pinSpacing: DABasics.Number _ ContactSize[cndObj]/2 + DesignRules.MinWidth[rules, branchLayer].w/2 + DesignRules.MinSpace[rules, branchLayer, branchLayer].s; trunkToEdge: DABasics.Number _ MAX[DesignRules.MinSpace[rules, branchLayer, branchLayer].s, DesignRules.MinSpace[rules, trunkLayer, trunkLayer].s] + MAX[ContactSize[cndObj], DesignRules.MinWidth[rules, trunkLayer].w]/2; designRuleParms _ NEW[Route.DesignRulesParametersRec _ [technology: rules.technology, horizLayer: horizLayer, vertLayer: vertLayer, trunkDirection: trunkDirection, trunkToTrunk: trunkToTrunk, pinSpacing: pinSpacing, trunkToEdge: trunkToEdge]]}; }.