<> <> <> DIRECTORY CD, CDInstances, CoreRouteFlat, GC, GCHybrid, PW, Rope; GCHybridImpl: CEDAR PROGRAM IMPORTS CD, CDInstances, GC, PW, Rope EXPORTS GCHybrid = BEGIN DiddleCells: PUBLIC PROC [design: CD.Design, structure: CoreRouteFlat.Structure] ~ { <> FOR insts: LIST OF CoreRouteFlat.Instance _ structure.instances, insts.rest WHILE insts#NIL DO <<>> instance: CoreRouteFlat.Instance _ insts.first; IF instance.layObject#NIL THEN { cdInstances: CD.InstanceList _ NIL; FOR netONodes: LIST OF CoreRouteFlat.NetONode _ instance.netONodes, netONodes.rest WHILE netONodes#NIL DO netONode: CoreRouteFlat.NetONode _ netONodes.first; netName: Rope.ROPE _ netONode.net.name; isPowerNet: BOOLEAN _ Rope.Equal[netName, "Vdd"] OR Rope.Equal[netName, "{Vdd}"]; isGroundNet: BOOLEAN _ Rope.Equal[netName, "Gnd"] OR Rope.Equal[netName, "{Gnd}"]; vddTap: CD.Object _ PW.Get[design, "VddTap.mask"]; gndTap: CD.Object _ PW.Get[design, "GndTap.mask"]; IF isPowerNet OR isGroundNet THEN { FOR pins: LIST OF CoreRouteFlat.Pin _ netONode.oNode.pins, pins.rest WHILE pins#NIL DO pin: CoreRouteFlat.Pin _ pins.first; tap: CD.Object _ IF isPowerNet THEN vddTap ELSE gndTap; trans: CD.Transformation _ SELECT pin.side FROM bottom => [off: [instance.layObject.bbox.x1 + pin.range.min, instance.layObject.bbox.y1], orient: original], top => [off: [instance.layObject.bbox.x1 + pin.range.max, instance.layObject.bbox.y2], orient: rotate180], left => [off: [instance.layObject.bbox.x1, instance.layObject.bbox.y1 + pin.range.max], orient: rotate270], right => [off: [instance.layObject.bbox.x2, instance.layObject.bbox.y1 + pin.range.min], orient: rotate90], ENDCASE => GC.Error[programmingError, "Call maintainer."]; cdInstances _ CONS [ CDInstances.NewInst[ ob: tap, trans: trans], cdInstances]; ENDLOOP}; ENDLOOP; instance.layShell _ PW.CreateCell[ instances: cdInstances, ir: CD.InterestRect[instance.layObject], name: Rope.Cat[structure.name, "Taps.mask"] ]}; ENDLOOP}; END.