DIRECTORY CD, CDBasics, CDInstances, CDProperties, CDRects, CDRoutingObjects, CDSimpleRules, CMosB, Core, CoreClasses, CoreCreate, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PW, PWCore, Rope, Route, Sisyph, SymTab; CoreRouteChangeLayers: CEDAR PROGRAM IMPORTS CD, CDBasics, CDInstances, CDProperties, CDRects, CDRoutingObjects, CDSimpleRules, CMosB, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PW, PWCore, Rope, Sisyph, SymTab = BEGIN ChangeLayersForm: TYPE = CoreRoute.ChangeLayersForm; ChangeLayersFormAry: TYPE = CoreRoute.ChangeLayersFormAry; ChangeLayersFormRec: TYPE = CoreRoute.ChangeLayersFormRec; WirePin: TYPE = CoreRoute.WirePin; WirePins: TYPE = CoreRoute.WirePins; Side: TYPE = CoreGeometry.Side; changeLayersLayoutProp: ATOM = $ChangeLayers; changeLayersLayoutRawProp: ATOM = $RawChangeLayers; changeLayersFormProp: ATOM = $ChangeLayersForm; wireWidthProp: ATOM = $w; technologyKey: ATOM = $cmosB; lambda: INT _ CDSimpleRules.GetTechnology[technologyKey].lambda; L4: INT _ 4*lambda; layDeco: CoreGeometry.Decoration _ PWCore.extractMode.decoration; schDeco: CoreGeometry.Decoration _ Sisyph.mode.decoration; Attribute: PWCore.AttributesProc = { data: CoreClasses.RecordCellType _ NARROW[cellType.data]; name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; form: ChangeLayersForm _ NEW[ChangeLayersFormAry _[vert:CD.commentLayer]]; subInst: CoreCreate.CellInstance _ data[0]; subObj: CD.Object _ PWCore.Layout[subInst.type]; subSize: CD.Position _ CD.InterestSize[subObj]; globals: Core.Wires _ CoreRoute.GlobalWires[cellType]; FOR side: Side IN Side DO GetBus: PROC[ws: Core.Wires] RETURNS[found: BOOL _ TRUE] = { IF ws=NIL THEN RETURN[FALSE]; IF ws.rest#NIL THEN ERROR; IF form.ary[side].bus#NIL AND form.ary[side].bus # ws.first THEN ERROR; form.ary[side].bus _ ws.first}; rw: REF INT; pIR: CD.Rect _ CD.InterestRect[CoreGeometry.GetObject[schDeco, cellType]]; cIR: CD.Rect _ CoreRoute.SchMappedIR[subInst]; min: INT _ SELECT side FROM left, right => cIR.y1 - pIR.y1, top, bottom => cIR.x1 - pIR.x1, ENDCASE => ERROR; max: INT _ SELECT side FROM left, right => cIR.y2 - pIR.y1, top, bottom => cIR.x2 - pIR.x1, ENDCASE => ERROR; wires: Core.Wires _ CoreRoute.OrderedAtomicSchWires[cellType, side]; form.ary[side].busLo _ GetBus [CoreRoute.OrderedAtomicSchWires[cellType, side, , min ]]; form.ary[side].busHi _ GetBus [CoreRoute.OrderedAtomicSchWires[cellType, side, max, ]]; form.ary[side].pins _ CoreRoute.FilteredInstanceLayoutPins[subInst, side]; form.ary[side].pins _ CoreRoute.FilterPins[form.ary[side].pins, wires, globals]; IF form.ary[side].bus#NIL THEN { rw _ NARROW [CoreProperties.GetWireProp[form.ary[side].bus, wireWidthProp]]; form.ary[side].busSize _ IF rw=NIL THEN L4 ELSE rw^*lambda}; ENDLOOP; form.vert _ CoreRoute.GetCellTypePropLayer[cellType, $VerticalMetal].layer; FOR side: Side IN Side DO VertLayer: PROC[sideLayer: CD.Layer] RETURNS[vertLayer: CD.Layer] = {RETURN[IF side=top OR side=bottom THEN sideLayer ELSE Other[sideLayer]]}; form.ary[side].min _ 0; IF side=top OR side=bottom THEN form.ary[side].max _ subSize.x ELSE form.ary[side].max _ subSize.y; IF form.ary[side].busLo THEN form.ary[side].busMin _ L4; IF form.ary[side].busHi THEN {IF side=top OR side=bottom THEN form.ary[side].busMax _ subSize.x - L4 ELSE form.ary[side].busMax _ subSize.y - L4}; AdjustPins345[form.ary[side].pins]; -- 3, 4, 5 => 4 lambda FOR pins: WirePins _ form.ary[side].pins, pins.rest WHILE pins#NIL DO pin: WirePin _ pins.first; sideLayer: CD.Layer _ Other[pin.layer]; IF form.vert#CD.commentLayer AND form.vert#VertLayer[sideLayer] THEN ERROR; form.vert _ VertLayer[sideLayer]; IF pin.wire=form.ary[side].bus THEN { form.ary[side].busMin _ MIN[form.ary[side].busMin, pin.min]; form.ary[side].busMax _ MAX[form.ary[side].busMax, pin.max]} ELSE { IF form.ary[side].busLo THEN form.ary[side].busMin _ MIN[form.ary[side].busMin, pin.min - L4 - form.ary[side].busSize]; IF form.ary[side].busHi THEN form.ary[side].busMax _ MAX[form.ary[side].busMax, pin.max + L4 + form.ary[side].busSize]}; ENDLOOP; form.ary[side].min _ MIN[form.ary[side].min, form.ary[side].busMin]; form.ary[side].max _ MAX[form.ary[side].max, form.ary[side].busMax]; ENDLOOP; IF form.ary[left].busMax > subSize.y AND form.ary[top].busMin < 0 OR form.ary[right].busMax > subSize.y AND form.ary[top].busMax > subSize.x OR form.ary[right].busMin < 0 AND form.ary[bottom].busMax > subSize.x OR form.ary[left].busMin < 0 AND form.ary[bottom].busMin < 0 THEN ERROR; form.ary[left].width _ MIN[form.ary[top].busMin, form.ary[bottom].busMin,0]; form.ary[bottom].width _ MIN[form.ary[left].busMin, form.ary[right].busMin,0]; form.ary[right].width _ MAX[form.ary[top].busMax, form.ary[bottom].busMax,0] - subSize.x; form.ary[top].width _ MAX[form.ary[left].busMax, form.ary[right].busMax,0] - subSize.y; form.ary[right].width _ MAX[form.ary[right].width, 0]; form.ary[top].width _ MAX[form.ary[top].width, 0]; FOR side: Side IN Side DO minHeight: INT _ IF form.ary[side].bus=NIL THEN 3*L4 ELSE 4*L4 + form.ary[side].busSize; form.ary[side].width _ MAX[form.ary[side].width+L4, minHeight] ENDLOOP; CoreRoute.FlushSchPinCache[subInst.type]; CoreRoute.FlushLayPinCache[subInst.type]; CoreProperties.PutCellTypeProp[cellType, changeLayersFormProp, form]}; Layout: PWCore.LayoutProc = { name: IO.ROPE _ CoreOps.GetCellTypeName[cellType]; data: CoreClasses.RecordCellType _ NARROW[cellType.data]; form: ChangeLayersForm _ NARROW[ CoreProperties.GetCellTypeProp[cellType, changeLayersFormProp]]; subObj: CD.Object _ PWCore.Layout[data[0].type]; subSize: CD.Position _ CD.InterestSize[subObj]; cdInstances: CD.InstanceList _ LIST [CDInstances.NewInst[ ob: subObj, trans: [CDBasics.NegOffset[CD.InterestBase[subObj]]] ]]; FOR side: Side IN Side DO nodes: SymTab.Ref _ SymTab.Create[]; width: INT _ form.ary[side].width; min: INT _ form.ary[side].min; max: INT _ form.ary[side].max; AddRect: PROC [wire: Core.Wire, size: CD.Position, lay: CD.Layer, off, min: INT] = { rect: CD.Object; IF side=top OR side=bottom THEN size _ [size.y, size.x]; rect _ CDRects.CreateRect[size, lay]; AddPositionedObject[wire, rect, off, min]}; AddVias: PROC [wire: Core.Wire, size: CD.Position, off, min: INT] = { vias: CD.Object _ IF side=top OR side=bottom THEN Vias[size.y, size.x] ELSE Vias[size.x, size.y]; AddPositionedObject[wire, vias, off, min]}; AddPositionedObject: PROC[wire: Core.Wire, obj: CD.Object, off, min: INT] = { label: Route.Label _ CoreRoute.LabelInternal[data.internal, wire]; pos: REF LIST OF CDRoutingObjects.PlacedObject _ NARROW[SymTab.Fetch[nodes, label].val]; szX: INT _ CD.InterestSize[obj].x; szY: INT _ CD.InterestSize[obj].y; po: CDRoutingObjects.PlacedObject _ SELECT side FROM top => [obj, [min, off ]], bottom => [obj, [min, width-off-szY ]], right => [obj, [off, min ]], left => [obj, [width-off-szX, min ]] ENDCASE=>ERROR; IF pos=NIL THEN { pos _ NEW[LIST OF CDRoutingObjects.PlacedObject _ NIL]; []_SymTab.Store[nodes, label, pos]}; pos^ _ CONS[po, pos^]}; routingIR: CD.Rect _ SELECT side FROM left => [0, min, width, max], right => [0, min, width, max], top => [min, 0, max, width], bottom => [min, 0, max, width], ENDCASE => ERROR; routingPos: CD.Position _ SELECT side FROM left => [-width, 0], right => [subSize.x, 0], top => [0, subSize.y], bottom => [0, -width], ENDCASE => ERROR; dstLay: CD.Layer _ IF side=top OR side=bottom THEN form.vert ELSE Other[form.vert]; srcLay: CD.Layer _ Other[dstLay]; IF form.ary[side].pins=NIL THEN LOOP; FOR pins: WirePins _ form.ary[side].pins, pins.rest WHILE pins#NIL DO pin: WirePin _ pins.first; size: INT _ pin.max - pin.min; IF pin.wire=form.ary[side].bus THEN AddRect[pin.wire, [3*L4, size], srcLay, 0, pin.min] ELSE { AddRect[pin.wire, [2*L4, size], srcLay, 0, pin.min]; AddVias[pin.wire, [L4, size], L4, pin.min]; AddRect[pin.wire, [width-L4, size], dstLay, L4, pin.min]}; ENDLOOP; IF form.ary[side].busLo THEN { size: INT _ form.ary[side].busSize; loc: INT _ form.ary[side].busMin; AddRect[form.ary[side].bus, [size+L4, size], dstLay, 3*L4, loc]; AddVias[form.ary[side].bus, [size, size], 3*L4, loc]}; IF form.ary[side].busHi THEN { size: INT _ form.ary[side].busSize; loc: INT _ form.ary[side].busMax-size; AddRect[form.ary[side].bus, [size+L4, size], dstLay, 3*L4, loc]; AddVias[form.ary[side].bus, [size, size], 3*L4, loc]}; IF form.ary[side].bus#NIL THEN { size: CD.Position _ [form.ary[side].busSize, form.ary[side].busMax-form.ary[side].busMin]; AddRect[form.ary[side].bus, size, srcLay, 3*L4, form.ary[side].busMin]}; cdInstances _ CONS [ CDInstances.NewInst[ ob: CDRoutingObjects.CreateRoutingObject[ nodes: CDRoutingObjects.CreateNodes[nodes], ir: routingIR], trans: [routingPos]], cdInstances]; ENDLOOP; obj _ PW.CreateCell[instances: cdInstances, name: name.Cat[".mask"] ]}; Decorate: PWCore.DecorateProc = { WireToLabels: PROC [wire: Core.Wire] RETURNS [labels: LIST OF Route.Label _ NIL] = {RETURN[LIST [CoreRoute.LabelInternal[data.internal, wire]]]}; data: CoreClasses.RecordCellType _ NARROW [cellType.data]; CoreRoute.DecorateRoutedArea[cellType: cellType, obj: obj, wireToLabels: WireToLabels]}; Adjust345: PROC[min, max: INT] RETURNS[minn, maxx: INT] = { minn _ min; maxx _ max; IF max-min IN (0..5*lambda] THEN { minn _ (min+max)/2 - 2*lambda; maxx _ (min+max)/2 + 2*lambda} }; AdjustPins345: PROC[pins: WirePins] = { FOR pins _ pins, pins.rest WHILE pins#NIL DO [pins.first.min, pins.first.max] _ Adjust345[pins.first.min, pins.first.max] ENDLOOP}; Other: PROC[lay: CD.Layer] RETURNS[CD.Layer] = {RETURN[IF lay=CMosB.met THEN CMosB.met2 ELSE CMosB.met]}; Vias: PROC[sizex, sizey: INT] RETURNS[obj: CD.Object] = { Bias: PROC[s: INT] RETURNS[bias:INT] = {RETURN[(s+d-((s+d)/(3*d))*3*d)/2]}; node: IO.ROPE _ "node"; insts: CD.InstanceList _ NIL; name: IO.ROPE _ IO.PutFR["Vias%gx%gy", IO.int[sizex], IO.int[sizey]]; via: CD.Object _ CDSimpleRules.Contact[technologyKey, CMosB.met, CMosB.met2]; d: INT _ L4/2; FOR x: INT _ Bias[sizex], x + 3*d WHILE x <= sizex-(2*d) DO FOR y: INT _ Bias[sizey], y + 3*d WHILE y <= sizey-(2*d) DO insts _ CONS[NEW[CD.InstanceRep _ [via, [[x, y]]]], insts]; CDProperties.PutProp[insts.first, $SignalName, node] ENDLOOP ENDLOOP; IF insts=NIL THEN ERROR; insts _ CONS[NEW[CD.InstanceRep _ [CDRects.CreateRect[[sizex, sizey], CMosB.met]]], insts]; CDProperties.PutProp[insts.first, $SignalName, node]; insts _ CONS[NEW[CD.InstanceRep _ [CDRects.CreateRect[[sizex, sizey], CMosB.met2]]],insts]; CDProperties.PutProp[insts.first, $SignalName, node]; obj _ PW.CreateCell[instances: insts, name: Rope.Cat["Adj.mask"], ir: [0, 0, sizex, sizey]]}; [] _ PWCore.RegisterLayoutAtom[changeLayersLayoutProp, Layout, Decorate, Attribute]; [] _ PWCore.RegisterLayoutAtom[changeLayersLayoutRawProp, Layout, Decorate]; END. $CoreRouteChangeLayers.mesa Copyright Σ 1987 by Xerox Corporation. All rights reserved. Don Curry November 8, 1987 12:45:22 pm PST Types and constants Attribute, Layout and Decorate Procs Compute min, max, busMin and busMax Check for conflicts in corner Two adjacent sides are both trying to extend into a corner. If this was a little smarter, it could do a fancy corner for = bus wires. Compute side widths Build routing objects. Auxillary procedures Vias: PROC[sizex, sizey: INT] RETURNS[obj: CD.Object] = {RETURN[ CDSimpleRules.LargeContact[$cmosB, NIL, [sizex, sizey], CMosB.met, CMosB.met2]]}; AddTo: PROC[side: Side, wire: Core.Wire, obj: CD.Object, off, min: INT, core: CD.Position, fullName: IO.ROPE, insts: CD.InstanceList] RETURNS[CD.InstanceList] = { inst: CD.Instance _ NEW[CD.InstanceRep _ [obj]]; len: INT _ CD.InterestSize[obj].x; wid: INT _ CD.InterestSize[obj].y; inst.trans _ SELECT side FROM top => [[min+wid, off+core.y ], rotate90], bottom => [[min+wid, -off-len ], rotate90], right => [[ off+core.x, min ], original], left => [[-off-len, min ], original] ENDCASE=>ERROR; CoreGeometry.AddPins[layDeco, wire, LIST[CoreGeometry.Instance[inst.ob, inst.trans]]]; CDProperties.PutProp[inst, $SignalName, fullName]; insts _ CONS[inst, insts]; RETURN[insts]}; Register layout atoms Κ ω˜™Icode™˜YJšœœ>˜XJšœœ˜6Jšœœ˜3šœ œ˜šœ œœ˜*Jšœ˜ Jšœœ˜#—Jšœœœ œ˜G—Jšœ)˜)Jšœ)˜)Jšœžœ(˜FJ˜—šžœ˜Jšœœœ)˜7Jšœ$œ˜:šœœ˜!Jšœ@˜@—Jšœœ)˜3Jšœ œœ˜1šœ œœ˜9Jšœ'œ˜D—JšŸ™šœ œ˜Jšœ%˜%Jšœœ˜"Jšœœ˜Jšœœ˜šžœ˜ šœœœœ˜FJšœœ˜Jšœ œ œ˜8Jšœ%˜%Jšœ+˜+——šžœ˜ šœœœ˜7šœœ œ œ ˜,Jšœ˜Jšœ˜—Jšœ+˜+——šžœœœœ˜MJšœB˜Bšœœœ ˜0Jšœ!˜'—Jšœœœ˜"Jšœœœ˜"šœ$œ˜4Jšœ!˜!Jšœ*˜*Jšœ$˜$Jšœ)œœ˜8—šœœœ˜Jš œœœœ!œ˜7Jšœ$˜$—Jšœœ ˜—šœ œœ˜%Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜—šœ œ œ˜*Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœœ˜—Jš œœ œ œ œ œ˜SJšœœ˜!Jšœ˜%šœ1œœ˜EJšœ˜Jšœœ˜ šœ˜šœ˜Jšœœ˜5—šœ˜Jšœœ˜6Jšœœœ ˜0Jšœœœ ˜:——Jšœ˜—šœœ˜Jšœœ˜#Jšœœ˜!Jšœ"œœ˜@Jšœ2œ˜<—šœœ˜Jšœœ˜#Jšœœ˜&Jšœ"œœ˜@Jšœ2œ˜<—šœœœ˜ šœœ ˜JšœF˜F—Jšœ,œ˜H—šœœ˜šœ˜šœ)˜)Jšœ+˜+Jšœ˜—Jšœ˜—Jšœ ˜ —Jšœ˜—Jšœœ?˜GJ˜—šžœ˜!š ž œœœ œœœ˜RJšœœœ2˜>—Jšœ#œ˜:JšœX˜X——™š ž œœ œœ œ˜;J˜šœ œœ˜"Jšœ˜Jšœ!˜!—J˜—šž œœ˜'šœœœ˜,Jšœ#ž œ!œ˜V—J˜—š žœœœœœ ˜.Jš œœœœ œ ˜:J˜—š žœœœœœ œ™@Jšœ#œ+™Q—J™š žœœœœœ ˜9Jš žœœœœœœ˜LJšœœœ ˜Jšœœœ˜Jš œœœœœ œ ˜HJšœœG˜OJšœœœ˜šœœœ˜;šœœœ˜;Jšœœœœ(˜;Jšœ5œœ˜E——Jšœœœœ˜JšœœœœH˜[Jšœ5˜5JšœœœœH˜[Jšœ5˜5JšœœU˜]J˜—šžœœ#œœœœœ œœœ™’Jšœœ œœ™0Jšœœœ™"Jšœœœ™"šœ œ™Jšœ-™-Jšœ-™-Jšœ-™-Jšœ)œœ™8—Jšœ$œ.™VJšœ2™2Jšœœ™Jšœ ™——™JšœU˜UJšœL˜LJ˜Jšœ˜—J˜J˜J˜—…—*¦<Γ