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Ö