DIRECTORY CCDUtils, CD, CDBasics, CDCells, CDDirectory, CDRects, CDSymbolicObjects, Convert, Core, CoreBlock, CoreFrame, CoreLibrary, CoreName, CoreOps, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, PW, PWC, Rope; IFUCoreDataImpl: CEDAR PROGRAM IMPORTS CCDUtils, CD, CDBasics, CDCells, CDDirectory, CDRects, CDSymbolicObjects, Convert, CoreBlock, CoreFrame, CoreLibrary, CoreName, CoreOps, CoreWire, CoreXform, HashTable, IFUCoreCells, IFUCoreData, CoreInstCell, IO, PW, PWC, Rope EXPORTS IFUCoreData = BEGIN ROPE: TYPE = Core.ROPE; NameLetterCode: TYPE = IFUCoreData.NameLetterCode; NameLetterCodeRec: TYPE = IFUCoreData.NameLetterCodeRec; NWMML: TYPE = PWC.NWMML; GND: ROPE _ CoreName.RopeNm["GND"]; VDD: ROPE _ CoreName.RopeNm["VDD"]; minus: ROPE _ CoreName.RopeNm["-"]; plus: ROPE _ CoreName.RopeNm["+"]; nil: ROPE _ CoreName.RopeNm["nil"]; pwrList: LIST OF REF _ LIST[GND, VDD]; Signal: SIGNAL = CODE; dpCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[ NEW[Core.CellClassRec _ [name: "IFUCoreData", recast: NIL]], ClassPrintProc]; ClassPrintProc: CoreOps.PrintClassProc = { dpData: IFUCoreData.DpCellData _ NARROW[data]; IO.PutF[out, "Data Path Subclass: %g Type: \n", IO.rope[dpData.subClass] ]; CoreOps.PrintWire[dpData.type.w, out, 2] }; RegisterSubClassExpand: PUBLIC PROC [type: CoreFrame.ExpandType, subClass: ROPE, expand: CoreFrame.ExpandProc] = { IF type = soft THEN [ ] _ HashTable.Store[expandSoft, subClass, NEW[CoreFrame.ExpandProc_ expand]] ELSE [ ] _ HashTable.Store[expandHard,subClass, NEW[CoreFrame.ExpandProc_ expand]]}; expandHard: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; expandSoft: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; Sequencial48: PUBLIC CoreXform.Xform _ CoreXform.GenXform[LIST[ [4, 0], [8, 1] ]]; Interleaved48: PUBLIC CoreXform.Xform _ CoreXform.GenXform[LIST[ [4, 1], [8, 0] ]]; CellProc: PUBLIC PROC [ subClass: ROPE _ NIL, type: ROPE _ NIL, name: ROPE _ NIL, left: REF _ NIL, right: REF _ NIL, top: REF _ NIL, bot: REF _ NIL, in: REF _ NIL, out: REF _ NIL, data: REF _ NIL, channels: INT _ 6, xform: CoreXform.Xform _ IFUCoreData.Interleaved48 ] RETURNS [cellType: Core.CellType] = { ctx: CoreName.Context _ CoreName.NewContext[]; public: CoreWire.CWire; strucType: CoreWire.CWire; expandSoftProc: REF CoreFrame.ExpandProc; expandHardProc: REF CoreFrame.ExpandProc; xforms: CoreXform.Xforms _ CoreXform.GenXforms[xform]; public _ [CoreOps.CreateWire[LIST[ RdListOfXfrmWires[ctx, "top", top, xforms], RdListOfXfrmWires[ctx, "bot", bot, xforms], RdListOfXfrmWires[ctx, "in", in, xforms], RdListOfXfrmWires[ctx, "out", out, xforms], RdListOfXfrmWires[ctx, "right", right, NIL], -- if needed put xform on rope RdListOfXfrmWires[ctx, "left", left, NIL], -- if needed put xform on rope RdListOfXfrmWires[ctx, "pwr", pwrList, NIL] ]]]; ctx _ CoreName.KillContext[ctx]; ctx _ CoreName.NewContext[]; strucType _ [RdListOfXfrmWires[ctx, "type", LIST[type], xforms][0]]; ctx _ CoreName.KillContext[ctx]; DeleteGV[public.f["top"].w]; DeleteGV[public.f["bot"].w]; cellType _ CoreOps.SetCellTypeName[ NEW [ Core.CellTypeRec _ [ class: dpCellClass, public: public.w, data: NEW[IFUCoreData.DpCellDataRec _ [ subClass: subClass, type: strucType, data: data, channels: channels ] ], properties: NIL] ], name]; expandSoftProc _ NARROW[HashTable.Fetch[expandSoft, subClass].value]; expandHardProc _ NARROW[HashTable.Fetch[expandHard, subClass].value]; IF expandSoftProc=NIL THEN Signal[]; IF expandHardProc=NIL THEN Signal[]; CoreFrame.SetFrameExpandProc[soft, cellType, expandSoftProc ]; CoreFrame.SetFrameExpandProc[hard, cellType, expandHardProc ]}; RdListOfXfrmWires: PROC[ctx: CoreName.Context, name: ROPE, ref: REF, xforms: CoreXform.Xforms] RETURNS[wire: Core.Wire] = { new: CoreXform.Xforms; [ref, new] _ Parse[ref]; IF new#NIL THEN xforms _ new; IF ISTYPE[ref, LIST OF REF] THEN wire _ GenWireFmList[ctx, NARROW[ ref], xforms] ELSE wire _ GenWireFmItem[ctx, ref, xforms]; [ ] _ CoreName.WireNm[wire, name]; FOR jj: INT IN [0..wire.size) DO CoreXform.SetXform[wire[jj], CoreXform.GenXform[xforms]] ENDLOOP }; DeleteGV: PROC[top: Core.Wire] = { -- doesn't work for top node DeleteGVMain: PROC[wire: Core.Wire] RETURNS[new: Core.Wire] = { IF wire.size=0 THEN RETURN[SELECT CoreName.WireNm[wire].n FROM GND, VDD => CoreOps.CreateWires[0] ENDCASE => wire] ELSE FOR i: INT IN [0..wire.size) DO wire[i] _ DeleteGVMain[wire[i]] ENDLOOP; RETURN[wire]}; [] _ DeleteGVMain[top]}; LISTIndexItem: PUBLIC PROC[list: LIST OF REF, index: INT] RETURNS[item: REF] = { FOR index _ index, index-1 WHILE index#0 AND list#NIL DO list_list.rest ENDLOOP; RETURN[IF list=NIL THEN NIL ELSE list.first]}; LISTLength: PUBLIC PROC [list: LIST OF REF] RETURNS[size: INT] = {FOR size _ 0, size+1 WHILE list#NIL DO list_list.rest ENDLOOP}; AddGVToLIST: PROC [list: LIST OF REF, rngWord: INT, indexGV: BOOL _ FALSE] RETURNS[new: LIST OF REF] = { FOR ii: INT DECREASING IN [0..MAX[rngWord+2, LISTLength[list]]) DO item: REF _ LISTIndexItem[list, ii]; IF ii=rngWord+1 THEN item _ IF indexGV THEN VDD.Cat["."] ELSE VDD; IF ii=rngWord THEN item _ IF indexGV THEN GND.Cat["."] ELSE GND; new _ CONS[item, new] ENDLOOP}; Parse: PROC[ref: REF] RETURNS[reff: REF, xforms: CoreXform.Xforms] = { IF ref=NIL THEN RETURN[NIL, NIL]; WITH ref SELECT FROM rope: Rope.ROPE => {[reff, xforms] _ ParseRope[rope]; RETURN[reff, xforms]}; text: REF TEXT => { rope: Rope.ROPE _ Rope.FromRefText[text]; [reff, xforms] _ ParseRope[rope]; RETURN[reff, xforms]}; list: LIST OF REF => { temp: LIST OF REF; FOR list _ list, list.rest WHILE list#NIL DO temp _ CONS[Parse[list.first].reff, temp]; ENDLOOP; list _ temp; temp _ NIL; FOR list _ list, list.rest WHILE list#NIL DO temp _ CONS[list.first, temp] ENDLOOP; RETURN[temp, NIL]}; list: LIST OF ROPE => { result, temp: LIST OF REF _ NIL; FOR list _ list, list.rest WHILE list#NIL DO temp _ CONS[ParseRope[list.first].reff, temp]; ENDLOOP; FOR temp _ temp, temp.rest WHILE temp#NIL DO result _ CONS[temp.first, result] ENDLOOP; RETURN[result, NIL]}; ENDCASE => {Signal[]; RETURN[NIL, NIL]}}; ParseRope: PROC[rope: ROPE] RETURNS[reff: REF, xforms: CoreXform.Xforms] = { ParseRopeItem: PROC RETURNS[REF _ NIL] = { item: ROPE; item _ ris.GetTokenRope[! IO.EndOfStream => CONTINUE].token; IF item=NIL THEN RETURN[NIL]; SELECT item.Fetch[0] FROM '(, '[ => RETURN[ParseRopeList[]]; '), '] => Signal[]; ENDCASE => RETURN[CoreName.RopeNm[item]]}; ParseRopeList: PROC RETURNS[lst: LIST OF REF _ NIL] = { temp: LIST OF REF _ NIL; DO item: ROPE _ ris.GetTokenRope[! IO.EndOfStream => EXIT].token; SELECT item.Fetch[0] FROM '(, '[ => lst _ CONS[ParseRopeList[], lst]; '), '] => EXIT; IN ['A..'Z] => {lst _ CONS[CoreName.RopeNm[item], lst]}; ENDCASE => {Signal[]; lst _ CONS[CoreName.RopeNm[item], lst]}; -- prob. bad name ENDLOOP; temp _ lst; lst _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO lst _ CONS[temp.first, lst] ENDLOOP}; ris: IO.STREAM _ IO.RIS[rope]; reff _ ParseRopeItem[] }; GenWireFmList: PROC[ctx: CoreName.Context, list: LIST OF REF, dims: CoreXform.Xforms] RETURNS[wire: Core.Wire] = { size: INT _ 0; IF list=NIL THEN RETURN[ CoreOps.CreateWires[0, nil] ]; FOR lst: LIST OF REF _ list, lst.rest WHILE lst#NIL DO size _ size + 1; ENDLOOP; wire _ NEW[Core.WireRec[size]]; size _ 0; FOR lst: LIST OF REF _ list, lst.rest WHILE lst#NIL DO wire[size] _ GenWireFmItem[ctx, lst.first, dims]; size _ size + 1; ENDLOOP}; GenWireFmItem: PROC[ctx: CoreName.Context, item: REF, dims: CoreXform.Xforms] RETURNS[wire: Core.Wire] = { IF item=NIL THEN RETURN[ CoreOps.CreateWires[0, nil] ]; WITH item SELECT FROM first: LIST OF REF => wire _ GenWireFmList[ctx, first, IF dims=NIL THEN NIL ELSE dims.rest]; first: Rope.ROPE => { SELECT first.Fetch[first.Length[]-1] FROM '., IN ['0..'9] => { size: INT _ 0; list: LIST OF REF; IF dims=NIL THEN wire _ CoreName.CtxWire[ctx, first, 0] ELSE { wire _ CoreName.CtxWire[ctx, first, dims.first.size]; IF wire=NIL THEN ERROR; -- probably missing '( )'s list _ BlowUpRope[first, dims.first.size]; FOR size: INT IN [0..wire.size) DO wire[size] _ GenWireFmItem[ctx, list.first, dims.rest]; list _ list.rest ENDLOOP} }; ENDCASE => wire _ CoreName.CtxWire[ctx, first, 0] }; ENDCASE => ERROR; IF wire=NIL THEN ERROR}; BlowUpRope: PROC[rope: ROPE, size: INT] RETURNS[ropes: LIST OF REF_NIL]= { FOR int: INT DECREASING IN [0..size) DO ropes _ CONS[ CoreName.RopeNm[ IO.PutFR["%g%g", IO.rope[rope], IO.int[int]] ], ropes ]; ENDLOOP}; CellWidth: PUBLIC PROC[chans: INT] RETURNS[INT] = { refCell: Core.CellType _ CoreLibrary.Get[IFUCoreCells.library, "DpLatchBlank"]; RETURN[chans*CCDUtils.metPitch+PWC.InterestSize[refCell].x]}; in0Rp: ROPE _ CoreName.RopeNm["in0"]; in1Rp: ROPE _ CoreName.RopeNm["in1"]; cont: CD.Object _ CCDUtils.Contact[CCDUtils.cmosPoly]; ybias: INT _ CCDUtils.polW/2 - cont.size.y/2; gndXBias: INT _ -cont.size.x/2 + 1*CCDUtils.metPitch - cont.size.x/2; vddXBias: INT _ -cont.size.x/2 + 2*CCDUtils.metPitch - cont.size.x/2; ConstantInputVariant: PUBLIC PROC [name, in0, in1: ROPE] RETURNS [cell: Core.CellType] ={ in0 _ CoreName.RopeNm[in0]; in1 _ CoreName.RopeNm[in1]; IF in0#GND AND in1#GND AND in0#VDD AND in1#VDD THEN RETURN[ CoreLibrary.Get[IFUCoreCells.library, name] ] ELSE { nMod0: ROPE _ SELECT in0 FROM VDD => "-V", GND => "-G", ENDCASE => "-="; nMod1: ROPE _ SELECT in1 FROM VDD => "-V", GND => "-G", ENDCASE => "-="; altName: ROPE _ name.Cat[nMod0, nMod1]; cell _ NARROW[HashTable.Fetch[IFUCoreCells.library.table, altName].value]; IF cell#NIL THEN RETURN[cell] ELSE { locs: LIST OF CD.Position _ NIL; orig: CD.Object _ CDDirectory.Fetch[IFUCoreCells.library.design, name].object; new: CD.Object _ CoreLibrary.Flatten[orig]; iBase: CD.Position _ CDBasics.BaseOfRect[CD.InterestRect[new]]; list: CD.InstanceList _ NARROW [new.specificRef, CD.CellPtr].contents; FOR list _ list, list.rest WHILE list # NIL DO OPEN Sym: CDSymbolicObjects; IF list=NIL THEN EXIT; IF Sym.IsPin[list.first.ob] THEN { inst: CD.Instance _ list.first; conn: BOOL; yLoc: INT; sides: CoreBlock.Sides; vddLoc, gndLoc: CD.Position; [sides, yLoc,] _ CoreBlock.GetInstSideLocSize[new, inst]; conn _ CoreBlock.OnSide[left, sides]; vddLoc _ [vddXBias, yLoc+ybias]; gndLoc _ [gndXBias, yLoc+ybias]; SELECT CoreName.RopeNm[Sym.GetName[inst]] FROM in0Rp => { SELECT in0 FROM VDD =>{Sym.SetName[inst, VDD]; IF conn THEN locs_CONS[vddLoc, locs]}; GND =>{Sym.SetName[inst, GND]; IF conn THEN locs_CONS[gndLoc, locs]}; ENDCASE }; in1Rp => { SELECT in1 FROM VDD =>{Sym.SetName[inst, VDD]; IF conn THEN locs_CONS[vddLoc, locs]}; GND =>{Sym.SetName[inst, GND]; IF conn THEN locs_CONS[gndLoc, locs]}; ENDCASE }; ENDCASE }; ENDLOOP; FOR locs _ locs, locs.rest WHILE locs#NIL DO [ ] _ PW.IncludeInCell[new, cont, locs.first] ENDLOOP; [ ] _ CDCells.RepositionCell[new, NIL]; cell _ CoreLibrary.ObjCell[new, altName]; CoreLibrary.Set[ IFUCoreCells.library, altName, cell] } } }; ConnSpec: TYPE = REF ConnSeqRec; ConnSeqRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF CnntRec]; CnntRec: TYPE = RECORD[name: ROPE, min, max: INT, layer: CD.Layer]; GenericCellRegistry: HashTable.Table _ HashTable.Create[]; CreateNameLetterCode: PUBLIC PROC [genericID: REF, list: LIST OF CoreWire.CWire, xformBit: INT] RETURNS[code: NameLetterCode] = { code _ InitNameLetterCode[]; IF genericID=NIL THEN code.name _ CoreName.ID["BitRouteRef"] ELSE { code.name _ NARROW[HashTable.Fetch[GenericCellRegistry, genericID].value]; IF code.name = NIL THEN { IF genericID=NIL THEN genericID _ CoreName.ID["BitRouteRef"]; code.name _ WITH genericID SELECT FROM rope: ROPE => genericID _ CoreName.RopeNm[rope], text: REF TEXT => genericID _ CoreName.RopeNm[Rope.FromRefText[text]], ENDCASE => CoreName.ID["BitRouteRef"]; [ ] _ HashTable.Store[GenericCellRegistry, genericID, code.name]} }; FOR list _ list, list.rest WHILE list#NIL DO code.name _ code.name.Cat[ "|" ]; FOR index: INT IN [0..list.first.w.size) DO code.name _ code.name.Cat [UniqueLetter[code, list.first.i[index].x[xformBit].n[] ] ] ENDLOOP; ENDLOOP}; Encode: PUBLIC PROC[code: NameLetterCode, name: ROPE] RETURNS[letter: ROPE] = {letter _ NARROW[HashTable.Fetch[code.letFmNm, name].value]}; Decode: PUBLIC PROC[code: NameLetterCode, letter: ROPE] RETURNS[name: ROPE] = {name _ NARROW[HashTable.Fetch[code.nmFmLet, letter].value]}; InitNameLetterCode: PROC RETURNS[code: NameLetterCode] = { code _ NEW[ NameLetterCodeRec _ [ name: NIL, letFmNm: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope], nmFmLet: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope], char: 'a, none: CoreName.RopeNm["="] ] ]; [ ] _ HashTable.Store[code.letFmNm, VDD, plus]; [ ] _ HashTable.Store[code.nmFmLet, plus, VDD]; [ ] _ HashTable.Store[code.letFmNm, GND, minus]; [ ] _ HashTable.Store[code.nmFmLet, minus, GND] }; UniqueLetter: PROC[code: NameLetterCode, name: ROPE] RETURNS[letter: ROPE] = { name _ CoreName.RopeNm[name]; IF name.Length[]=0 OR name=nil THEN RETURN[code.none]; letter _ NARROW[HashTable.Fetch[code.letFmNm, name].value]; IF letter#NIL THEN RETURN[letter]; letter _ CoreName.RopeNm[Convert.RopeFromChar[code.char, FALSE]]; [ ] _ HashTable.Store[code.letFmNm, name, letter]; [ ] _ HashTable.Store[code.nmFmLet, letter, name]; SELECT code.char FROM IN ['a..'z) => code.char _ code.char + 1; 'z => code.char _ 'A; IN ['A..'Z) => code.char _ code.char + 1; ENDCASE => Signal[]}; DpBitRoute: PUBLIC PROC[ specificCell: Core.CellType, genericCell: Core.CellType, rowWire: CoreWire.CWire, phyBit: INT, channels: INT, specificName: ROPE _ NIL ] RETURNS [glue: Core.CellType] = { renameProc: CoreInstCell.RenameProc ~ {new _ code.Decode[letter: old]; IF new=NIL THEN Signal[]; RETURN[new]}; code: IFUCoreData.NameLetterCode _ CreateNameLetterCode [genericID: genericCell, xformBit: phyBit, list: LIST[ rowWire.f["top" ], rowWire.f["in" ], rowWire.f["out" ], rowWire.f["right" ], rowWire.f["left" ], rowWire.f["bot" ] ]]; genericObj: CD.Object; generic: Core.CellType _ CoreLibrary.Get[IFUCoreCells.library, code.name]; IF generic=NIL THEN { size: INT _ PWC.InterestSize[specificCell].y; list: LIST OF NWMML _ CCDUtils.SidePinList[specificCell, left]; count: INT _ 0; connSpec: ConnSpec; FOR temp: LIST OF NWMML _ list, temp.rest WHILE temp#NIL DO count _ count + 1 ENDLOOP; connSpec _ NEW[ConnSeqRec[count+2]]; connSpec[0] _ [NIL, 0, 0, CCDUtils.cmosMet]; connSpec[connSpec.size-1] _ [NIL, size, size, CCDUtils.cmosMet]; FOR count IN [1..connSpec.size-1) DO connSpec[count] _ [ name: code.Encode[list.first.name], min: list.first.min, max: list.first.max, layer: list.first.layer ]; list _ list.rest ENDLOOP; genericObj _ IncludeBitWiring[code, connSpec, rowWire, phyBit, channels]; generic _ CoreLibrary.ObjCell[genericObj, code.name ]; CoreLibrary.Set[IFUCoreCells.library, code.name, generic]}; IF specificName = NIL THEN specificName _ CoreName.CellNm[specificCell].n; IF specificName = NIL THEN specificName _ CoreName.ID["BitRoute"] ELSE specificName _ Rope.Cat[specificName, "BitRoute"]; glue _ CoreInstCell.SpecificGeneric[generic, renameProc]; glue _ CoreFrame.NewFrameCell[0, specificName, [cell: glue ]] }; IncludeBitWiring: PROC[code: IFUCoreData.NameLetterCode, connSpec: ConnSpec, rowWire: CoreWire.CWire, xBit, channels: INT] RETURNS[cell: CD.Object] = { OPEN CM: CCDUtils; Same: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = {RETURN[Rope.Equal[connSpec[idx1].name, connSpec[idx2].name]]}; tIdx: CARDINAL _ connSpec.size-1; bIdx: CARDINAL _ 0; cell _ CDCells.CreateEmptyCell[]; FOR col: INT IN [0..channels) DO Add: PROC[idx1, idx2: CARDINAL] RETURNS[BOOL] = { IF ~Same[idx1, idx2] THEN RETURN[FALSE]; loc.y _ connSpec[idx1].min; size.y _ connSpec[idx2].max - connSpec[idx1].min; IF size.y < 0 THEN ERROR; CCDUtils.AddRet[cell:cell, size: size, loc: loc, level: CM.cmosMet]; RETURN[TRUE]}; size: CD.Position _ [CM.metW, 0]; loc: CD.Position _ [CM.leftTail+col*CM.metPitch-CM.metW/2, 0]; connSpec[tIdx].name _ code.Encode[rowWire.f["top"].i[col].x[xBit].n]; connSpec[bIdx].name _ code.Encode[rowWire.f["bot"].i[col].x[xBit].n]; SELECT connSpec[tIdx].name FROM GND, VDD => connSpec[tIdx].name_NIL ENDCASE; SELECT connSpec[bIdx].name FROM GND, VDD => connSpec[bIdx].name_NIL ENDCASE; IF connSpec[tIdx].name#NIL THEN FOR row: INT IN [bIdx..tIdx) DO CM.PutPin[cell, [CM.metW, CM.metW], [loc.x, connSpec[tIdx].max-CM.metW], CM.cmosMet, connSpec[tIdx].name]; IF Add[ row, tIdx] THEN EXIT; REPEAT FINISHED => { log.PutF["Orphan top signal: %g", IO.rope[IFUCoreData.Decode[code, connSpec[tIdx].name]]]; Signal[]} ENDLOOP; IF connSpec[bIdx].name#NIL THEN FOR row: INT DECREASING IN (bIdx..tIdx) DO CM.PutPin[cell, [CM.metW, CM.metW], [loc.x, 0], CM.cmosMet, connSpec[bIdx].name]; IF Add[ bIdx, row] THEN EXIT; REPEAT FINISHED => IF ~Same[bIdx, tIdx] THEN { log.PutF["Orphan bottom signal: %g", IO.rope[IFUCoreData.Decode[code, connSpec[bIdx].name]]]; Signal[]} ENDLOOP; ENDLOOP; FOR row: INT IN (bIdx..tIdx) DO ctct: CD.Object _ CM.Contact[connSpec[row].layer]; wire: CD.Object; wWdth: INT _ connSpec[row].max - connSpec[row].min; Pin: PROC[side: {left, right}] = { xLoc: INT _ IF side = right THEN channels*CM.metPitch-CM.cnctSize ELSE 0; CM.PutPin[cell, [CM.cnctSize, wWdth], [xLoc, connSpec[row].min], connSpec[row].layer, connSpec[row].name]}; IF connSpec[row].layer = CM.cmosMet2 THEN { wire _ CDRects.CreateRect[[channels*CM.metPitch, wWdth], connSpec[row].layer]; Pin[left]; Pin[right]; [] _ PW.IncludeInCell[cell, wire, [0, connSpec[row].min]]}; FOR col: INT IN [0..channels) DO wLen: INT _ (channels-1-col)*CM.metPitch + CM.rightTail; wLoc: CD.Position _ [CM.leftTail + col*CM.metPitch, connSpec[row].min]; connSpec[tIdx].name _ code.Encode[rowWire.f["top"].i[col].x[xBit].n]; connSpec[bIdx].name _ code.Encode[rowWire.f["bot"].i[col].x[xBit].n]; IF ~Same[row, tIdx] AND ~Same[row, bIdx] THEN LOOP; wire _ CDRects.CreateRect[[wLen, wWdth], connSpec[row].layer]; Pin[right]; [] _ PW.IncludeInCell[cell, ctct, [wLoc.x-CM.cnctSize/2, wLoc.y-(CM.cnctSize-wWdth)/2]]; [] _ PW.IncludeInCell[cell, wire, wLoc]; ENDLOOP; ENDLOOP; CDCells.SetInterestRect[cell, [0, 0, channels*CM.metPitch, connSpec[tIdx].max]]; [ ] _ CDCells.RepositionCell[cell, NIL] }; BlockSides: PUBLIC PROC[cell: Core.CellType, cwire: CoreWire.CWire] = { BlockSideIfNotUsed: PROC[wire: Core.Wire] = { sides: CoreBlock.Sides _ CoreBlock.GetWireSide[wire]; name: ROPE _ CoreName.WireNm[wire].n; ltrt: BOOL _ cwire.f["left"].f[name].w#NIL OR cwire.f["right"].f[name].w#NIL; IF NOT ltrt THEN RETURN; SELECT name FROM VDD, GND => RETURN ENDCASE; IF cwire.f["left" ].f[name].w=NIL THEN sides _ CoreBlock.DelSide[left, sides]; IF cwire.f["right" ].f[name].w=NIL THEN sides _ CoreBlock.DelSide[right, sides]; CoreBlock.PutWireSide[wire, sides]}; CoreOps.VisitRootAtomics[cell.public, BlockSideIfNotUsed]}; log: IO.STREAM _ CoreFrame.GetLog[]; END. ÒIFUCoreDataImpl.mesa, Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by Curry, October 1, 1986 10:50:33 am PDT Don Curry October 27, 1986 12:46:28 pm PST If ref is a list then sform applies to it. If not, xforms applies to the elements of the list; Can't use this because wires are shared. Sharing maybe useful in the future if the row public gets used to make a celltype, but for now, rowWires are just used to package names. DeleteGV: PROC[wire: Core.Wire] = { SELECT CoreName.WireNm[wire].n FROM GND, VDD => [ ] _ CoreOps.SetShortWireName[wire, NIL] ENDCASE; FOR i: INT IN [0..wire.size) DO DeleteGV[wire[i]] ENDLOOP}; IN ['0..'9] => { Vertical connections Horizontal connections Ê‚˜šœ™Jšœ<™—Jš œœœœœ™;—J˜šŸ œœœœœœ œœœ˜QJš œœ œœœœ˜PJš œœœœœœ˜.—šŸ œœœœœœœœ˜@Jš œœœœœœ˜@—šŸ œœœœœ œ œœ˜JJšœœœœ˜š œœ œœœ˜BJšœœ˜$Jšœœœ œœ œœ˜BJšœ œœ œœ œœ˜@Jšœœ œ˜——J˜š Ÿœœœœœ˜FJš œœœœœœ˜!šœœ˜Jšœ œ(œ˜Mšœœœ˜Jšœ œ˜)Jšœ"œ˜8—šœœœœ˜Jšœœœœ˜šœœœ˜,Jšœœ œ˜3—Jšœœ˜š œœœœœœ˜SJšœœ˜——šœœœœ˜Jšœœœ œ˜ šœœœ˜,Jšœœ$œ˜7—šœœ˜)Jšœ œœ˜-—Jšœ œ˜—Jšœœœ˜)—J˜—š Ÿ œœœœœ˜Lš Ÿ œœœœœ˜*Jšœœ˜ Jšœœœ˜šœ˜Jšœœ˜-Jšœ œ˜Jšœ™Jšœœ˜8Jšœœ ˜P—Jšœ˜—Jšœœ˜Jš œœœœœœ˜R—Jš œœœœœ˜Jšœ˜—J˜J˜š Ÿ œœœœœ˜UJšœ˜Jšœœ˜Jšœœœœ ˜7Jšœœœœœœœœ˜PJšœœ˜)š œœœœœœ˜6JšœCœ˜L—J˜—šŸ œœœ˜MJšœ˜Jšœœœœ ˜7šœœ˜šœœœœ˜Jš œ!œœœœœ ˜F—šœ œ˜šœ˜)šœœ˜Jšœœ˜Jšœœœœ˜šœ˜ Jšœ(˜,šœ˜Jšœ5˜5Jš œœœœ ˜2Jšœ*˜*šœœœ˜"Jšœ7˜7Jšœœ˜————Jšœ.˜5——Jšœœ˜—Jšœœœœ˜—J˜šŸ œœœœœœœœœ˜Jš œœ œœ ˜'šœœ˜ Jšœœœ œ ˜@Jšœ œ˜———J˜š Ÿ œœœœœœ˜3JšœO˜OJšœ7˜=—J˜Jšœœ˜(Jšœœ˜'Jšœœ/˜9Jšœ œ%˜1Jšœ œ9˜FJšœ œ9˜FJ˜šŸœ œœ œ˜YJšœ˜Jšœ˜šœœœœœœœ˜.Jšœœ0œ˜AJš œœœœœ œ œ ˜HJš œœœœœ œ œ ˜HJšœ œ˜'Jšœ œ=˜Mš œœœœœ˜$Jš œœœœ œ˜ JšœœH˜PJšœœ&˜-Jšœœ!œ˜@Jšœœœ˜Fšœœœ˜.Jšœ˜Jšœœœœ˜šœœ˜"Jšœœ˜Jšœœ˜ Jšœœ˜ Jšœ˜Jšœœ ˜Jšœ9˜9Jšœ'˜'Jšœ!˜!Jšœ!˜!šœ$˜.šœ ˜ šœ˜Jš œœœœœ˜EJš œœœœœ˜EJšœ˜ ——šœ ˜ šœ˜Jš œœœœœ˜EJš œœœœœ˜EJšœ˜ ——Jšœ˜ ——Jšœ˜—šœœœ˜,Jšœœ&œ˜6—Jšœ(˜(Jšœ)˜)Jšœ<˜<———J™Jšœ œœ ˜ Jš œ œœœœœ ˜>Jš œ œœœ œ œ˜DJ˜JšŸœ'˜:J˜šŸœœ˜!š œ œœœœ˜=Jšœ˜!—Jšœ˜šœ ˜Jšœœ˜+šœ˜Jšœ œ8˜Jšœ œœ˜Jšœ œœœ˜=šœ œ œ˜&Jšœœ'˜1Jšœœœ8˜FJšœœ˜,—JšœD˜D———šœœœ˜,Jšœ!˜!šœœœ˜+šœ˜Jšœ<œ˜D——Jšœ˜ ——J˜š Ÿœœœœœ œ˜NJšœ œ-˜=—š Ÿœœœœœœ˜NJšœœ/˜=—J˜šŸœœœ˜:šœœ˜!Jšœœ˜ JšœQ˜QJšœP˜PJšœ ˜ Jšœ!˜!—Jšœ$œ ˜0Jšœ+œ˜0Jšœ$œ ˜1Jšœ+œ˜2—J˜š Ÿ œœœœ œ˜NJšœ˜Jšœœ œœ ˜6Jšœ œ,˜;Jšœœœœ ˜"Jšœ9œ˜AJšœ2˜2Jšœ2˜2šœ ˜Jšœ(˜*Jšœ˜Jšœ'˜)Jšœ˜——J˜šŸ œœœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ œ˜Jšœ œ˜Jšœœœœ˜<šœ'˜'Jš œ!œœœ œ˜H—šœ8˜8šœ1œ˜6Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜——Jšœ œ˜JšœK˜Kšœ œœ˜Jšœœ$˜/Jšœœœœ,˜AJšœ œ˜Jšœ˜š œœœœœœ˜;Jšœœ˜—Jšœ œ˜$Jšœœ˜1Jšœœ ˜@šœœ˜$šœ˜Jšœ#˜#Jšœ˜Jšœ˜Jšœ˜—Jšœœ˜—JšœI˜IJšœ7˜7Jšœ;˜;—Jšœœœ0˜Jšœ˜Jšœ'˜+Jšœ3˜7—Jšœ9˜9šœ@˜@J˜J˜——šŸœœ`œ˜zJšœœ ˜Jšœœ ˜š Ÿœœ œœœ˜0Jšœœ8˜?—Jšœœ˜!Jšœœ˜Jšœ!˜!Jšž™šœœœ˜ š Ÿœœ œœœ˜1Jšœœœœ˜(Jšœ˜Jšœ2˜2Jšœ œœ˜Jšœ8œ ˜DJšœœ˜—Jšœœ ˜!Jšœœœ œ ˜>JšœE˜EJšœF˜FJš œœœœœœ˜LJš œœœœœœ˜Lš œœœœœœ˜?šœœœ#œ˜HJšœ!˜!—š œœœœœ˜2šœ!˜!Jšœ6˜8—Jšœ œ˜——šœœœœœ œœ˜JJšœœœ5˜Qšœœœœœœœ˜Lšœ$˜$Jšœ6˜8—Jšœ œ˜——Jšœ˜—Jšž™šœœœ˜Jšœœ œ˜3Jšœœ˜Jšœœ)˜3šŸœœ˜"Jš œœœœ œ œ œ˜Išœœ˜%JšœE˜E——šœœ œ˜+Jšœ$œ(˜NJšžœžœ˜Jšœœ4˜;—šœœœ˜ Jšœœœ œ ˜8Jšœœ œœ˜GJšœE˜EJšœF˜FJšœœœœ˜3Jšœ>˜>Jšžœ˜ šœœ˜!Jšœœœ˜6—Jšœœ!˜(Jšœ˜—Jšœ˜—Jšœ.œ ˜PJšœ*˜*—J˜šŸ œ œ0˜GšŸœœ˜-Jšœ5˜5Jšœœ˜%Jš œœœœœ˜MJšœ ˜Jš œœœœœœ˜,Jšœœ)˜PJšœœ)˜PJšœ$˜$—JšœŸœŸœ˜;—J˜J˜˜$J˜—Jšœ˜—J™—…—J‚eÖ