DIRECTORY CC, CD, CDDirectory, CDIO, CDRects, CDRoutingObjects, CDSimpleRules, CDViewer, CMosB, Core, CoreClasses, CoreCreate, CoreDirectory, CoreGeometry, CoreOps, IO, PLAOps, PWCore, TilingClass, REFBit, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerOps, WireIconExtras; CCImpl: CEDAR PROGRAM IMPORTS CD, CDDirectory, CDIO, CDRects, CDRoutingObjects, CDSimpleRules, CDViewer, CMosB, CoreClasses, CoreCreate, CoreDirectory, CoreGeometry, CoreOps, IO, PLAOps, PWCore, TilingClass, REFBit, RefTab, Rope, RopeList, Sisyph, TerminalIO, ViewerOps, WireIconExtras EXPORTS CC = BEGIN ROPE: TYPE = Rope.ROPE; ROPES: TYPE = LIST OF Rope.ROPE; CellType: TYPE = Core.CellType; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; TileVarieties: TYPE = RECORD[glue: REF GlueTiles, and, or: REF NormalTiles]; GlueTiles: TYPE = ARRAY RowType OF ARRAY GlueCellType OF CellType; GlueCellType: TYPE = {leftSide, between, rightSide}; NormalTiles: TYPE = ARRAY RowType OF ARRAY NormalCellType OF CellType; NormalCellType: TYPE = {left, right, nc, extra}; RowType: TYPE = {header, footer, conn, dataUp, dataDn, blank}; DriverTiles: TYPE = REF DriverTileArry; DriverTileArry: TYPE = ARRAY DriverTileType OF CellType; DriverTileType: TYPE = {left, in, between, extra, out2, out1, rightHalf}; vddNm: ROPE _ "Vdd"; gndNm: ROPE _ "Gnd"; inNm: ROPE _ "in"; in0Nm: ROPE _ "in0"; in1Nm: ROPE _ "in1"; outNm: ROPE _ "out"; out0Nm: ROPE _ "out0"; out1Nm: ROPE _ "out1"; logicInNm: ROPE _ "logicIn"; logicOutNm: ROPE _ "logicOut"; rowsPerDr: INT _ 3; -- not easily changed outsPerExtra: INT _ 10; -- can be changed rowsPerExtra: INT _ 10; -- can be changed layRules: ATOM _ $cmosB; TileBuffer: REF TileVarieties _ NIL; DriverBuffer: DriverTiles _ NIL; RoutingCells: RefTab.Ref _ RefTab.Create[]; Signal: SIGNAL = CODE; ExpToPlaCell: PUBLIC PROC[expr: REF, type: ATOM _ NIL] RETURNS[cell: CellType] = { pla: PLAOps.PLA _ PLAOps.ExpressionToPLA[expr]; IF type=NIL THEN type _ $buffered; SELECT type FROM $basic => cell _ PLABodyBasic[pla]; $bufferedBot => cell _ PLABuffered[pla]; $basicRt => cell _ PLABodyBasic[pla, TRUE]; ENDCASE => ERROR}; PLABuffered: PROC[pla: PLAOps.PLA] RETURNS[cell: CellType] = { logic: CellType _ PLABodyBasic[pla]; bufs: CellType _ BufferedPLADrivers[pla]; vdd: Wire _ CoreOps.CreateWires[0, vddNm]; gnd: Wire _ CoreOps.CreateWires[0, gndNm]; logicIn: Wire _ WireIconExtras.RefWire[pla.data, logicInNm, TRUE]; logicOut: Wire _ WireIconExtras.RefWire[pla.out, logicOutNm, FALSE]; in: Wire _ WireIconExtras.RefWire[pla.data, inNm, FALSE]; out: Wire _ WireIconExtras.RefWire[pla.out, outNm, FALSE]; logicI: CoreCreate.CellInstance _ CoreCreate.Instance[logic, [inNm, logicIn], [outNm, logicOut], [vddNm, vdd], [gndNm, gnd] ]; bufsI: CoreCreate.CellInstance _ CoreCreate.Instance[bufs, [inNm, in], [outNm, out], [logicInNm, logicIn], [logicOutNm, logicOut], [vddNm, vdd], [gndNm, gnd] ]; StripSubWireNames[logicIn]; StripSubWireNames[logicOut]; AddSubWireNamePrefix[to: out, prefix: "Nxt"]; cell _ CoreCreate.Cell[ public: CoreCreate.WireList[LIST[in, out, vdd, gnd]], onlyInternal: CoreCreate.WireList[LIST[logicIn, logicOut]], instances: LIST[bufsI, logicI], name: pla.name ]; PWCore.SetAbutY[cell]; RETURN[cell]}; PLAInSB: PUBLIC PROC[cx: CC.Context, tttFile: ROPE] RETURNS[cell: CellType] = { pla: PLAOps.PLA _ PLAOps.ReadPLAFile [tttFile.Cat[".ttt"], TerminalIO.TOS[], TRUE]; rec: CoreClasses.RecordCellType _ NEW[CoreClasses.RecordCellTypeRec[0]]; in: Wire _ WireIconExtras.RefWire[pla.data, "in", TRUE]; out: Wire _ WireIconExtras.RefWire[pla.out, "out", FALSE]; public: Wire _ CoreOps.CreateWire[LIST[in]]; internal: Wire _ CoreOps.CreateWire[LIST[in]]; flatIn: Wire _ CoreOps.CreateWire[Flatten[in]]; flatInOrd: Wire _ CoreOps.CreateWire[Flatten[ReorderWire[in, GetSideNames[cx, right]]]]; insAtTop: BOOL _ GetSideNames[cx, top] #NIL; insAtBot: BOOL _ GetSideNames[cx, bottom] #NIL AND ~insAtTop; ins: NAT _ flatIn.size/2; nofOrCols: NAT _ NofOrCols[MAX[CoreOps.WireBits[out], GetMinOuts[cx]]]; leftSize: INT _ 44 * CMosB.lambda; betweenSize: INT _ 16 * CMosB.lambda; rightSize: INT _ 16 * CMosB.lambda; blankSize: INT _ 8 * CMosB.lambda; biasX: INT _ 48 * CMosB.lambda; biasY: INT _ 12 * CMosB.lambda; colAnd: INT _ 16 * CMosB.lambda; colOr: INT _ 8 * CMosB.lambda; halfColSize: INT _ 8 * CMosB.lambda; rowSize: INT _ 24 * CMosB.lambda; halfRowSize: INT _ 16 * CMosB.lambda; obj: CD.Object; contObj: CD.Object _ CDSimpleRules.Contact[layRules, CMosB.met, CMosB.met2]; contW: INT _ CD.InterestSize[contObj].x; metW: INT _ CDSimpleRules.MinWidth[layRules, CMosB.met]; met2W: INT _ CDSimpleRules.MinWidth[layRules, CMosB.met2]; iSizeX: NAT _ leftSize +ins*colAnd +betweenSize +nofOrCols*colOr +rightSize; iSizeY: NAT _ blankSize + ins*rowSize + blankSize; nodes: LIST OF CDRoutingObjects.Node; cell _ CoreClasses.CreateRecordCell[public, internal, NIL, tttFile.Cat["InSB"]]; FOR indexX: INT IN [0..ins) DO FOR polarity: INT IN [0..2) DO node: CDRoutingObjects.Node; pub: Wire _ flatIn[2*indexX + polarity]; name: ROPE _ CoreOps.GetFullWireName[public, pub]; indexY: INT _ WireIndex[flatInOrd, pub]/2; refX: INT _ biasX + indexX * colAnd + polarity * halfColSize; refY: INT _ biasY + indexY * rowSize + polarity * halfRowSize; verYSize: INT _ SELECT TRUE FROM insAtTop AND insAtBot => iSizeY, insAtTop => iSizeY-refY, insAtBot => refY, ENDCASE => ERROR; horSize: CD.Position _ [iSizeX-refX, metW]; verSize: CD.Position _ [met2W, verYSize]; horPos: CD.Position _ [refX, refY-metW/2]; verPos: CD.Position _ [refX-met2W/2, (IF insAtBot THEN 0 ELSE refY)]; contPos: CD.Position _ [refX-contW/2, refY-contW/2]; horObj: CD.Object _ CDRects.CreateRect[horSize, CMosB.met]; verObj: CD.Object _ CDRects.CreateRect[verSize, CMosB.met2]; pos: LIST OF CDRoutingObjects.PlacedObject _ NIL; IF name=NIL THEN ERROR; pos _ CONS[[ horObj, horPos], pos]; --pins _ CONS[[horObj, [horPos]], pins]; pos _ CONS[[ verObj, verPos], pos]; --pins _ CONS[[verObj, [verPos]], pins]; pos _ CONS[[ contObj, contPos], pos]; node _ CDRoutingObjects.CreateNode [pos, LIST[[$SignalName, name], [$InstanceName, name]]]; nodes _ CONS[node, nodes]; ENDLOOP; ENDLOOP; obj _ CDRoutingObjects.CreateRoutingObject[nodes, [x1: 0, y1: 0, x2: iSizeX, y2: iSizeY]]; PWCore.SetLayout[cell, $Value, $PWCoreValue, obj]}; PLAOutDrHeader: PUBLIC PROC[tttFile: ROPE] RETURNS[cell: CellType] = { pla: PLAOps.PLA _ PLAOps.ReadPLAFile[tttFile.Cat[".ttt"], TerminalIO.TOS[], TRUE]; out: Wire _ WireIconExtras.RefWire[pla.out, "out", FALSE]; outSize: INT _ CoreOps.WireBits[out]; minSize: NAT _ (rowsPerDr-1)*outSize; outFill: INT _ MAX[pla.termList.length, minSize] - minSize; header: CellType _ Get["CC.DrHeader.sch", TRUE]; blank: CellType _ Get["CC.DrBlank.sch", TRUE]; name: ROPE _ "DrHeader"; insts: CoreCreate.CellInstances _ LIST[CoreCreate.Instance[header]]; IF outFill=0 THEN RETURN[header]; name _ IO.PutFR["%gWith%gBlanks", IO.rope[name], IO.int[outFill]]; FOR i: INT IN [1..outFill] DO insts _ CONS[CoreCreate.Instance[blank], insts]; ENDLOOP; cell _ CoreCreate.Cell[ public: CoreOps.CopyWire[header.public], instances: insts, name: name]; PWCore.SetAbutY[cell]}; PLABody: PUBLIC PROC[cx: CC.Context, tttFile: ROPE] RETURNS[cell: CellType] = { pla: PLAOps.PLA _ PLAOps.ReadPLAFile[tttFile, TerminalIO.TOS[], TRUE]; minOuts: INT _ GetMinOuts[cx]; rightNames: ROPES _ GetSideNames[cx, right]; cell _ PLABodyBasic[pla, rightNames#NIL, rightNames, minOuts]}; PLABodyBasic: PROC [pla: PLAOps.PLA, horOuts: BOOL_FALSE, rtNms: ROPES_NIL, minOuts: INT_0] RETURNS[cell: CellType] = { vdd: Wire _ CoreOps.CreateWires[0, vddNm]; gnd: Wire _ CoreOps.CreateWires[0, gndNm]; in: Wire _ WireIconExtras.RefWire[pla.data, "in", TRUE]; out: Wire _ WireIconExtras.RefWire[pla.out, "out", FALSE]; flatIn: Wire _ CoreOps.CreateWire[Flatten[in]]; flatOut: Wire _ CoreOps.CreateWire[Flatten[out]]; flatOutOrd: Wire _ CoreOps.CreateWire[Flatten[ReorderWire[out, rtNms]]]; public: Wire _ NIL; nofRows: NAT _ 2 + (IF horOuts THEN flatOut.size+MAX[flatOut.size*(rowsPerDr-1), pla.termList.length] ELSE pla.termList.length); nofOrCols: NAT _ NofOrCols[MAX[flatOut.size, minOuts] ]; nofAndCols: NAT _ flatIn.size/2; row: INT _ 0; up: BOOL _ FALSE; cRow: INT _ 0; fillLt: INT _ 0; ta: TilingClass.TileArray _ NEW[TilingClass.TileArrayRec[nofRows]]; terms: LIST OF PLAOps.Term _ NIL; data: PLAOps.Term _ NIL; GetRow: PROC[type: RowType] RETURNS[rowRef: TilingClass.TileRow ] = { AndBit: PROC[index: INT] RETURNS[NormalCellType] = { RETURN[SELECT type FROM dataUp, dataDn => SELECT PLAOps.GetInQrt [data, REFBit.Desc[pla.data].bitForm[index].firstBit] FROM zero => left, one => right, ENDCASE => nc, ENDCASE => nc]}; OrBit: PROC[index: INT] RETURNS[NormalCellType] = { IF (index+1) MOD (outsPerExtra+1) = 0 THEN RETURN[extra]; index _ index - index/(outsPerExtra+1); IF index >= flatOut.size THEN RETURN[nc]; SELECT type FROM conn => IF flatOutOrd[cRow]=flatOut[index] THEN RETURN[left]; dataUp, dataDn => IF PLAOps.GetOutQrt [data, REFBit.Desc[pla.out].bitForm[index].firstBit]=one THEN RETURN[left]; ENDCASE; RETURN[nc]}; TileIt: PROC[ cell: CellType, pubType: {in, out, none} _ none, index: INT _ 0, header: BOOL_FALSE ] = { pas: LIST OF CoreCreate.PA _ NIL; SELECT pubType FROM in => pas _ LIST[[in0Nm, flatIn[2*index+0]], [in1Nm, flatIn[2*index+1]] ]; out => pas _ LIST[[outNm, flatOut[index]]]; ENDCASE; IF header THEN pas _ CONS[[vddNm, vdd], CONS[[gndNm, gnd], pas]]; rowRef[col] _ NEW[TilingClass.TileRec _ [cell, pas, IsRoutingCell[cell]]]; col _ col+1}; col: INT _ 0; tiles: REF TileVarieties _ GetPLATiles[]; rowRef _ NEW[TilingClass.TileRowRec[1 + nofAndCols + 1 + nofOrCols + 1]]; SELECT type FROM conn => { up _ FALSE}; dataUp, dataDn => { IF terms = NIL THEN data _ NIL ELSE {data _ terms.first; terms _ terms.rest}; type _ IF data=NIL THEN blank ELSE IF (up_~up) THEN dataUp ELSE dataDn}; ENDCASE; TileIt[ tiles.glue[type][leftSide], none, 0]; FOR i: INT IN [0..nofAndCols) DO IF row=0 AND AndBit[i]#extra THEN {TileIt[tiles.and[type][AndBit[i]], in, i]} ELSE {TileIt[tiles.and[type][AndBit[i]]]}; ENDLOOP; TileIt[ tiles.glue[type][between]]; FOR i: INT IN [0..nofOrCols) DO outI: INT _ i-i/(outsPerExtra+1); IF row=0 AND OrBit[i]#extra AND outI < flatOut.size THEN {TileIt[ tiles.or[type][OrBit[i]], out, outI]} ELSE {TileIt[ tiles.or[type][OrBit[i]]]} ENDLOOP; IF type#conn THEN {TileIt[tiles.glue[type][rightSide], none, 0, (type=header OR type=footer)]} ELSE {TileIt[tiles.glue[type][rightSide] ]} }; IF horOuts THEN terms _ GetHorOutsTermList[pla, flatOut, flatOutOrd] ELSE { size: INT _ pla.termList.length + (pla.termList.length-1)/rowsPerExtra; term: PLAOps.Term _ pla.termList.end; FOR index: INT DECREASING IN[0..size) DO IF (index+1) MOD (outsPerExtra+1) # 0 THEN {terms _ CONS[PLAOps.CopyTerm[term], terms]; term _ term.last} ELSE {terms _ CONS[NIL, terms]} ENDLOOP }; FOR row IN [0..ta.size) DO SELECT TRUE FROM row=0 => {ta[row]_ GetRow[footer]; fillLt _ rowsPerDr-1}; row+1=nofRows => {ta[row]_ GetRow[header]}; fillLt#0 => {ta[row]_ GetRow[dataUp]; fillLt _ fillLt -1}; cRow=flatOut.size => {ta[row]_ GetRow[dataUp]}; ~horOuts => {ta[row]_ GetRow[dataUp]}; --fillLt not used unless horOuts ENDCASE => {ta[row]_ GetRow[conn]; fillLt_rowsPerDr-1; cRow_cRow+1}; ENDLOOP; IF ~horOuts THEN AddSubWireNamePrefix[to: out, prefix: "Nxt"]; cell _ TilingClass.CreateTiling[ public: CoreOps.CreateWire[LIST[in, out, vdd, gnd]], tileArray: ta, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: pla.name, props: NIL ]}; BufferedPLADrivers: PROC[pla: PLAOps.PLA] RETURNS[cell: CellType]={ vdd: Wire _ CoreOps.CreateWires[0, vddNm]; gnd: Wire _ CoreOps.CreateWires[0, gndNm]; lIn: Wire _ WireIconExtras.RefWire[pla.data, logicInNm, TRUE]; lOut: Wire _ WireIconExtras.RefWire[pla.out, logicOutNm, FALSE]; dIn: Wire _ WireIconExtras.RefWire[pla.data, inNm, FALSE]; dOut: Wire _ WireIconExtras.RefWire[pla.out, outNm, FALSE]; flatLIn: Wire _ CoreOps.CreateWire[Flatten[lIn]]; flatLOut: Wire _ CoreOps.CreateWire[Flatten[lOut]]; flatDIn: Wire _ CoreOps.CreateWire[Flatten[dIn]]; flatDOut: Wire _ CoreOps.CreateWire[Flatten[dOut]]; nofOrCols: NAT _ NofOrCols[flatDOut.size]; nofOrColExs: NAT _ nofOrCols/(outsPerExtra+1); nofOrColOut: NAT _ nofOrCols - nofOrColExs; nofAndCols: NAT _ flatDIn.size; drivers: DriverTiles _ GetPLADriverTiles[]; ta: TilingClass.TileArray _ NEW[TilingClass.TileArrayRec[1]]; orIndex: INT _ 0; extras: INT _ 0; col: INT _ 0; TileIt: PROC[ cell: CellType, pubType: {in, out2, out1, filler} _ filler, index: INT _ 0] = { pas: LIST OF CoreCreate.PA _ LIST[[vddNm, vdd], [gndNm, gnd]]; SELECT pubType FROM in => pas _ CONS[[inNm, flatDIn[index]], CONS[[out0Nm, flatLIn[2*index+0]], CONS[[out1Nm, flatLIn[2*index+1]], pas]]]; out1 => pas _ CONS[[in0Nm, flatLOut[index]], CONS[[out0Nm, flatDOut[index]], pas]]; out2 => pas _ CONS[[in0Nm, flatLOut[index]], CONS[[out0Nm, flatDOut[index]], CONS[[in1Nm, flatLOut[index+1]], CONS[[out1Nm, flatDOut[index+1]], pas]]]]; ENDCASE; ta[0][col] _ NEW[TilingClass.TileRec _ [cell, pas, IsRoutingCell[cell]]]; col _ col+1}; ta[0] _ NEW[TilingClass.TileRowRec [1 + nofAndCols + 1 + nofOrColExs + nofOrColOut/2 + 2]]; TileIt[ drivers[left], filler]; FOR i: INT IN [0..nofAndCols) DO TileIt[drivers[in], in, i] ENDLOOP; TileIt[ drivers[between], filler]; WHILE orIndex < nofOrCols DO IF ((orIndex+1) MOD (outsPerExtra+1)) = 0 THEN {TileIt[ drivers[extra], filler]; orIndex _ orIndex+1; extras _ extras+1; LOOP} ELSE {IF orIndex+1=nofOrCols THEN {TileIt[ drivers[out1], out1, orIndex-extras]; orIndex _ orIndex+1} ELSE {TileIt[ drivers[out2], out2, orIndex-extras]; orIndex _ orIndex+2}}; ENDLOOP; TileIt[ drivers[rightHalf], filler]; IF ((nofOrCols-extras) MOD 2)=0 THEN TileIt[ drivers[rightHalf], filler]; StripSubWireNames[lIn]; -- to prevent confusion with driver in subWire names StripSubWireNames[lOut]; -- to prevent confusion with driver out subWire names cell _ TilingClass.CreateTiling[ public: CoreOps.CreateWire[LIST[dIn, dOut, lIn, lOut, vdd, gnd]], tileArray: ta, neighborX: TilingClass.LayoutNeighborX, neighborY: TilingClass.LayoutNeighborY, name: pla.name, props: NIL ]}; GetMinOuts: PROC[cx: Sisyph.Context] RETURNS[nofOrCols: INT] = { RETURN[IF (cx=NIL OR NOT Sisyph.FetchInt[cx, "CCPLAOuts"].found) THEN 0 ELSE Sisyph.FetchInt[cx, "CCPLAOuts"].value]}; NofOrCols: PROC[nofOuts: INT] RETURNS[nofOrCols: INT] = {RETURN[nofOuts+(nofOuts-1)/outsPerExtra]}; StripSubWireNames: PROC[w: Wire] = { IF w.size=0 THEN RETURN; FOR i: INT IN [0..w.size) DO []_CoreOps.SetShortWireName[w[i], NIL]; StripSubWireNames[w[i]]; ENDLOOP}; AddSubWireNamePrefix: PROC[to: Wire, prefix: ROPE] = { FOR i: INT IN [0..to.size) DO name: ROPE _ CoreOps.GetShortWireName[to[i]]; IF name.Length[]=0 OR to[i].size>0 THEN ERROR; []_CoreOps.SetShortWireName[to[i], Rope.Cat[prefix, name]] ENDLOOP;}; GetHorOutsTermList: PROC[pla: PLAOps.PLA, flatOut, flatOutOrd: Wire] RETURNS[terms: LIST OF PLAOps.Term _ NIL] = { SeqTermLists: TYPE = REF SeqTermListsRec; SeqTermListsRec: TYPE = RECORD[SEQUENCE size: CARDINAL OF LIST OF PLAOps.Term]; TwoTermRecs: TYPE = RECORD[t1, t2: PLAOps.TermRec]; MoveFromTermsToOuts: PROC[idx: INT] = { terms _ CONS[NIL, terms]; IF terms=NIL THEN RETURN; FOR list: LIST OF PLAOps.Term _ terms, list.rest WHILE list.rest#NIL DO term: PLAOps.Term _ list.rest.first; IF PLAOps.GetOutQrt[term, idx]#one THEN {list.rest _ list.rest.rest; terms _ terms.rest; outs[idx] _ CONS[term, outs[idx]]; RETURN}; ENDLOOP; FOR list: LIST OF PLAOps.Term _ terms, list.rest WHILE list.rest#NIL DO term: PLAOps.Term _ list.rest.first; FOR i: INT IN [0..outs.size) DO IF PLAOps.GetOutQrt[term, i]#one THEN FOR sub: LIST OF PLAOps.Term _ outs[i], sub.rest WHILE sub#NIL DO IF PLAOps.GetOutQrt[sub.first, idx]#one THEN { [term^, sub.first^] _ TwoTermRecs[sub.first^, term^]; list.rest _ list.rest.rest; terms _ terms.rest; outs[idx] _ CONS[term, outs[idx]]; RETURN} ENDLOOP; ENDLOOP; REPEAT FINISHED => ERROR ENDLOOP}; outForm: PLAOps.Format _ REFBit.Desc[pla.out].bitForm; end: PLAOps.Term; outs: SeqTermLists _ NEW[SeqTermListsRec[pla.termList.outBits]]; FOR output: INT IN [pla.termList.length..flatOutOrd.size*2) DO terms _ CONS[PLAOps.NewTerm[pla.termList.inBits, pla.termList.outBits], terms] ENDLOOP; FOR term: PLAOps.Term _ pla.termList.end, term.last WHILE term#NIL DO terms _ CONS[PLAOps.CopyTerm[term], terms] ENDLOOP; FOR output: INT IN [0..flatOutOrd.size) DO outs[output] _ NIL ENDLOOP; FOR output: INT IN [0..flatOutOrd.size) DO FOR index: INT IN [0..flatOut.size) DO IF flatOutOrd[output] # flatOut[index] THEN LOOP; MoveFromTermsToOuts[ outForm[index].firstBit ]; MoveFromTermsToOuts[ outForm[index].firstBit ]; EXIT REPEAT FINISHED => ERROR ENDLOOP; ENDLOOP; FOR output: INT DECREASING IN [0..flatOutOrd.size) DO FOR index: INT IN [0..flatOut.size) DO IF flatOutOrd[output] # flatOut[index] THEN LOOP; FOR sub: LIST OF PLAOps.Term _ outs[outForm[index].firstBit], sub.rest WHILE sub#NIL DO terms _ CONS[sub.first, terms] ENDLOOP; outs[outForm[index].firstBit] _ NIL; ENDLOOP ENDLOOP; terms _ ReverseTerms[terms]; -- make last first UNTIL end#NIL DO end _ terms.first; terms _ terms.rest ENDLOOP; -- remove end term terms _ ReverseTerms[terms]; -- make first first terms _ CONS[end, terms]; -- add end term to beginning FOR list: LIST OF PLAOps.Term _ terms, list.rest WHILE list#NIL DO FOR i: CARDINAL IN [0..list.first.out.wdSize) DO IF list.first.out[i].d#0 THEN EXIT; REPEAT FINISHED => list.first _ NIL ENDLOOP ENDLOOP}; ReverseTerms: PROC[terms: LIST OF PLAOps.Term] RETURNS[new: LIST OF PLAOps.Term] = {FOR terms _ terms, terms.rest WHILE terms#NIL DO new_CONS[terms.first, new] ENDLOOP}; WireIndex: PROC[big, little: Wire] RETURNS[index: INT _ -1] = { FOR index: INT IN [0..big.size) DO IF big[index]=little THEN RETURN[index] ENDLOOP; RETURN[-1]}; ReorderWire: PROC[wire: Wire, names: ROPES, extras: BOOL _ FALSE] RETURNS[Wire] = { wires: Wires _ NIL; nms: ROPES _ CONS[NIL, names]; IF names=NIL THEN RETURN[wire]; IF extras THEN FOR nms _ nms, nms.rest WHILE nms.rest#NIL DO index: INT _ CoreOps.GetWireIndex[wire, nms.rest.first]; IF index=-1 THEN nms.rest _ nms.rest.rest REPEAT FINISHED => names _ nms.rest ENDLOOP; FOR names _ names, names.rest WHILE names#NIL DO index: INT _ CoreOps.GetWireIndex[wire, names.first]; IF index=-1 THEN { TerminalIO.PutF ["The icon wire name \"%g\" is not an element of the PLA interface.\n", IO.rope[names.first]]; ERROR}; wires _ CONS[wire[index], wires] ENDLOOP; RETURN[ CoreOps.CreateWire[ CoreOps.Reverse[wires]]]}; Flatten: PROC[wire: Wire] RETURNS[wires: Wires _ NIL] = { temp: Wires; IF wire.size=0 THEN RETURN[LIST[wire]]; FOR ii: INT IN [0..wire.size) DO FOR temp _ Flatten[wire[ii]], temp.rest WHILE temp#NIL DO wires _ CONS[temp.first, wires] ENDLOOP ENDLOOP; temp _ wires; wires _ NIL; FOR temp _ temp, temp.rest WHILE temp#NIL DO wires _ CONS[temp.first, wires] ENDLOOP}; GetSideNames: PROC[cx: CC.Context, side: CoreGeometry.Side] RETURNS[names: ROPES] = { obj: CD.Object _ Sisyph.GetCDObj[cx]; cell: CellType _ Sisyph.ES[CDDirectory.Name[obj, Sisyph.GetDesign[cx]], cx]; eachSortedPin: CoreGeometry.EachSortedPinProc = {names _ CONS[CoreOps.GetShortWireName[wire], names]}; []_CoreGeometry.EnumerateSortedSides [Sisyph.mode.decoration, cell, side, eachSortedPin]; names _ RopeList.Reverse[names]}; RegisterRoutingCell: PROC[cell: CellType] = {[]_RefTab.Store[RoutingCells, cell, cell]}; IsRoutingCell: PROC[cell: CellType] RETURNS[isRoutingCell: BOOL] = {RETURN[RefTab.Fetch[RoutingCells, cell].found]}; Get: PROC [name: ROPE, routingOnly: BOOL] RETURNS [cellType: CellType] ~ { cellType _ GetCellType[name]; IF (NARROW[cellType.data, CoreClasses.RecordCellType].size=0)#routingOnly THEN Signal[]; IF routingOnly THEN RegisterRoutingCell[cellType]}; GetCellType: PROC [name: ROPE] RETURNS [cellType: CellType] ~ { library: CoreDirectory.Library _ CoreDirectory.FetchLibrary["CMOSB"]; cellType _ CoreDirectory.Fetch[library, name]; IF cellType=NIL THEN { designName: IO.ROPE _ name.Substr[0, name.Find["."]]; cellName: IO.ROPE _ name.Substr[name.Index[0, "."]+1]; design: CD.Design _ CDViewer.FindDesign[designName]; cx: CC.Context; IF design=NIL THEN { design _ CDIO.ReadDesign[designName]; IF design=NIL THEN ERROR; ViewerOps.CloseViewer[CDViewer.CreateViewer[design, FALSE]]}; -- caches the design cx _ Sisyph.Create[design]; cellType _ Sisyph.ExtractSchematicByName[name: cellName, cx: cx]; []_CoreDirectory.Insert[library, name, cellType]}}; FlipY: PROC[orig: CellType] RETURNS[ct: CellType] = { flipName: ROPE _ Rope.Cat["FlipY", CoreOps.GetCellTypeName[orig]]; library: CoreDirectory.Library _ CoreDirectory.FetchLibrary["CMOSB"]; ct _ CoreDirectory.Fetch[library, flipName]; IF ct = NIL THEN { ct _ PWCore.RotateCellType[orig, $FlipY]; []_CoreDirectory.Insert[library, flipName, ct]; IF IsRoutingCell[orig] THEN RegisterRoutingCell[ct]}}; GetPLATiles: PROC RETURNS[tiles: REF TileVarieties] = { IF TileBuffer # NIL THEN RETURN[TileBuffer]; TerminalIO.PutRope["Initialize PLA tiles\n"]; tiles _ TileBuffer _ NEW[TileVarieties]; tiles.glue _ NEW[GlueTiles]; tiles.and _ NEW[NormalTiles]; tiles.or _ NEW[NormalTiles]; tiles.glue [header][leftSide] _ Get["CC.HPlaHLeftSide.sch", TRUE]; tiles.glue [header][between] _ Get["CC.HPlaHBetween.sch", TRUE]; tiles.glue [header][rightSide] _ Get["CC.HPlaHRightSide.sch", TRUE]; tiles.and [header][nc] _ Get["CC.HPlaHAnd.sch", TRUE]; tiles.or [header][nc] _ Get["CC.HPlaHOr.sch", FALSE]; tiles.or [header][extra] _ Get["CC.HPlaHOrEx.sch", TRUE]; tiles.glue [footer][leftSide] _ FlipY[ tiles.glue [header][leftSide] ]; tiles.glue [footer][between] _ FlipY[ tiles.glue [header][between] ]; tiles.glue [footer][rightSide] _ FlipY[ tiles.glue [header][rightSide] ]; tiles.and [footer][nc] _ FlipY[ tiles.and [header][nc] ]; tiles.or [footer][nc] _ FlipY[ Get["CC.BPlaHOr.sch", FALSE]]; tiles.or [footer][extra] _ FlipY[ tiles.or [header][extra] ]; tiles.glue [blank][leftSide] _ Get["CC.HPlaBLeftSide.sch", TRUE]; tiles.glue [blank][between] _ Get["CC.HPlaBBetween.sch", TRUE]; tiles.glue [blank][rightSide] _ Get["CC.HPlaBRightSide.sch", TRUE]; tiles.and [blank][nc] _ Get["CC.HPlaBAnd.sch", TRUE]; tiles.or [blank][nc] _ Get["CC.BOr.sch", TRUE]; tiles.or [blank][extra] _ Get["CC.HPlaBOrEx.sch", TRUE]; tiles.glue [conn][leftSide] _ Get["CC.HPlaBLeftSide.sch", TRUE]; tiles.glue [conn][between] _ Get["CC.HPlaBBetween.sch", TRUE]; tiles.glue [conn][rightSide] _ Get["CC.HPlaCRightSide.sch", TRUE]; tiles.and [conn][nc] _ Get["CC.HPlaBAnd.sch", TRUE]; tiles.or [conn][left] _ Get["CC.COr.sch", TRUE]; tiles.or [conn][nc] _ Get["CC.COrNC.sch", TRUE]; tiles.or [conn][extra] _ Get["CC.HPlaCOrEx.sch", TRUE]; tiles.glue [dataUp][leftSide] _ Get["CC.HPlaDLeftSide.sch", FALSE]; tiles.glue [dataUp][between] _ Get["CC.HPlaDBetween.sch", TRUE]; tiles.glue [dataUp][rightSide] _ Get["CC.HPlaDRightSide.sch", TRUE]; tiles.and [dataUp][left] _ Get["CC.DAndLt.sch", FALSE]; tiles.and [dataUp][right] _ Get["CC.DAndRt.sch", FALSE]; tiles.and [dataUp][nc] _ Get["CC.DAnd.sch", TRUE]; tiles.or [dataUp][left] _ Get["CC.DOr.sch", FALSE]; tiles.or [dataUp][nc] _ Get["CC.DOrNC.sch", TRUE]; tiles.or [dataUp][extra] _ Get["CC.HPlaDOrEx.sch", TRUE]; tiles.glue [dataDn][leftSide] _ tiles.glue [dataUp][leftSide]; tiles.glue [dataDn][between] _ FlipY[ tiles.glue [dataUp][between] ]; tiles.glue [dataDn][rightSide] _ FlipY[ tiles.glue [dataUp][rightSide] ]; tiles.and [dataDn][left] _ tiles.and [dataUp][left]; tiles.and [dataDn][right] _ tiles.and [dataUp][right]; tiles.and [dataDn][nc] _ tiles.and [dataUp][nc]; tiles.and [dataDn][extra] _ tiles.and [dataUp][extra]; tiles.or [dataDn][left] _ FlipY[ tiles.or [dataUp][left] ]; tiles.or [dataDn][nc] _ FlipY[ tiles.or [dataUp][nc] ]; tiles.or [dataDn][extra] _ FlipY[ tiles.or [dataUp][extra] ]; RETURN[tiles]}; GetPLADriverTiles: PROC RETURNS[drivers: DriverTiles] = { IF DriverBuffer # NIL THEN RETURN[DriverBuffer]; TerminalIO.PutRope["Initialize PLA Buffer tiles\n"]; drivers _ DriverBuffer _ NEW[DriverTileArry]; drivers[left] _ Get["CC.BPlaDrLeftSide.sch", TRUE]; drivers[in] _ Get["CC.BPlaDrDualIn.sch", FALSE]; drivers[between] _ Get["CC.BPlaDrBetween.sch", TRUE]; drivers[extra] _ Get["CC.BPlaDrOrEx.sch", TRUE]; drivers[out2] _ Get["CC.BPlaDrDualOutInv.sch", FALSE]; drivers[out1] _ Get["CC.BPlaDrSingOutInv.sch", FALSE]; drivers[rightHalf] _ Get["CC.BPlaDrRightSideHalf.sch", TRUE]}; END. žCCImpl.mesa Don Curry August 15, 1987 5:26:35 pm PDT Types, constants and globals Exported Procedures $latchedBot => cell _ XXX[pla]; $clockedRt => cell _ XXX[pla]; $latchedRt => cell _ XXX[pla]; pins: LIST OF CoreGeometry.Instance _ NIL; CoreGeometry.AddPins[PWCore.extractMode.decoration, pub, pins]; PWCore.PutObject[PWCore.extractMode.decoration, cell, obj]}; []_PWCore.Layout[header]; []_PWCore.Layout[blank]; Domestic Procedures The type of PLA is implied by where the ouputs are specified in the icon. output names on right => output connections positioned every 3 rows `out' or output names on bottom => output connections at bottom `in' or input names may be on top or bottom or both. MainLine GetRow Code MainLine PLAOut Code This should not be quaified by horOuts. Its just too painful to change the dozen or so icons in IFUSch just yet. MainLine Code AddSubWireNamePrefixIfClash: PROC[to, ck: Wire, prefix: ROPE] = { FOR i: INT IN [0..to.size) DO CkClash: PROC [w: Wire] = {clash _ clash OR CoreOps.GetShortWireName[w].Equal[name]}; clash: BOOL _ FALSE; name: ROPE _ CoreOps.GetShortWireName[to[i]]; IF name.Length[] > 0 THEN [] _ CoreOps.VisitRootAtomics[ck, CkClash]; IF clash THEN []_CoreOps.SetShortWireName[to[i], Rope.Cat[prefix, name]]; IF to[i].size>0 THEN AddSubWireNamePrefixIfClash[to[i], ck, prefix]; ENDLOOP}; Assumes 3 rows per driver MoveOutsBackToTerms Tiles See also DPImpl.GetSchCT - same except for RoutingCell registration Get: PROC [cx: CC.Context, name: ROPE, routingOnly: BOOL] RETURNS [cellType: CellType] ~ { design: CD.Design _ Sisyph.GetDesign[cx]; importeeName: IO.ROPE _ name.Substr[0, name.Index[0, "."]]; IF design.name.Equal[importeeName] THEN name _ name.Substr[name.Index[0, "."]+1] ELSE IF CDDirectory.Fetch[design, name]=NIL THEN { rootName: IO.ROPE _ name.Substr[name.Index[0, "."]+1]; ob: CD.Object _ CDImports.CreateImportFromCache[design, rootName, importeeName, TRUE]; IF NOT CDDirectory.Include[design, ob, name, FALSE] THEN ERROR}; cellType _ Sisyph.ExtractSchematicByName[name: name, cx: cx]; IF (NARROW[cellType.data, CoreClasses.RecordCellType].size=0)#routingOnly THEN Signal[]; IF routingOnly THEN RegisterRoutingCell[cellType]}; Κq˜šœ ™ Jšœ(™(—J˜šΟk œ˜ Jšœœ•œm˜Š—J˜šΟnœœœ˜Jšœ’œl˜‡Jšœœ˜ Jš˜headšΟl™Jšœœœ˜Jš œœœœœ˜"Jšœ œ˜!Jšœ œ ˜Jšœ œ˜Jš œœœœœ˜MJš œ œœ œœœ ˜DJšœœ"˜4Jš œœœ œœœ ˜GJšœœ˜0Jšœ œ1˜?Jšœœœ˜(Jšœœœœ ˜8Jšœœ5˜IJšœ œ ˜Jšœ œ ˜Jšœ œ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ ˜Jšœ œ˜Jšœ œΟc˜*Jšœœ ˜*Jšœœ ˜)Jšœ œ˜Jšž œœœ˜%Jšž œœ˜"Jšž œ!˜-Jšžœœœ˜—šŸ™š ž œœœœœœ˜RJšœœ ˜1Jšœœœ˜"šœ˜Jšœ%˜%Jšœ(˜(Jšœœ™Jšœ&œ˜,Jšœœ™Jšœœ™Jšœœ˜—J˜—šž œœ œœ˜>Jšœ&˜&Jšœ+˜+Jšœ4˜4Jšœ4˜4Jšœ?œ˜EJšœAœ˜HJšœ9œ˜@Jšœ9œ˜@šœ/žœ˜>Jšœ˜Jšœ˜J˜J˜—šœ.žœ˜Jšœœ˜Jšœ œ œ)˜GJšœ œ˜#Jšœ œ˜%Jšœ œ˜$Jšœ œ˜#Jšœ œ˜!Jšœ œ˜!Jšœ œ˜!Jšœ œ˜!Jšœ œ˜%Jšœ œ˜"Jšœ œ˜%Jšœœ˜Jšœ œA˜MJšœœœ˜)Jšœœ/˜:Jšœœ0˜;Jšœ œA˜MJ•StartOfExpansionT -- [x1: D2Basic.Number, y1: D2Basic.Number, x2: D2Basic.Number, y2: D2Basic.Number]šœ œ'˜3Jšœ œœ˜'Jšœ6œ˜Pšœ œœ ˜šœ œœ˜Jšœ˜Jšœ+˜+Jšœœ(˜3Jšœœ!˜,Jšœœ6˜@Jšœœ7˜Ašœ œœœ˜ Jšœ œ˜ Jšœ˜Jšœ˜Jšœ œ˜—Jšœ œ!˜,Jšœ œ˜)Jšœœ#˜-Jš œœœ œœ˜EJšœ œ)˜4Jšœœ1˜;Jšœœ2˜Jšœ œ˜&Jšœ œ˜&Jšœ œœ)˜˜GJšœ%˜%š œœ œœ ˜(šœ œ˜%Jšœ œ1˜CJšœ œœ˜%—Jšœ˜ ———š œœœœœ˜+Jšœ=˜=Jšœ,˜,Jšœ=˜=Jšœ/˜/Jšœ*  ˜JJšœ@˜GJšœ˜—Jš’'™'Jš’H™HJšœ œ/˜?šœ ˜ Jšœœ˜6Jšœ˜Jšœ(˜(Jšœ(˜(Jšœ˜Jšœ œ˜—J˜—šžœœ œœ˜CJšœ4˜4Jšœ4˜4Jšœ<œ˜BJšœ>œ˜EJšœ9œ˜@Jšœ:œ˜AJšœ3˜3Jšœ5˜5Jšœ3˜3Jšœ5˜5Jšœ œ˜+Jšœ œ˜/Jšœ œ˜,Jšœ œ˜ Jšœžœ˜,Jšœœ˜AJšœ œ˜Jšœ œ˜Jšœœ˜šžœœ˜ Jšœ˜Jšœ+˜+Jšœœ ˜Jš œœœ œœ˜?šœ ˜šœ ˜ Jšœ˜Jšœ˜"Jšœ&˜*—šœ˜Jšœ˜Jšœ"˜&—šœ˜Jšœ˜Jšœ˜Jšœ˜ Jšœ&˜*—Jšœ˜—Jšœ œ9˜IJšœ ˜ —šœœ˜"Jšœ8˜8—Jšœ˜Jš œœœœœ˜DJšœ"˜"šœ˜šœœ˜)JšœKœ˜Tšœœ˜JšœD˜HJšœF˜J——Jšœ˜—Jšœ$˜$šœœ˜Jšœ%˜)—JšœL˜LJšœN˜NJšœ ™ šœ ˜ Jšœœ"˜CJšœ˜Jšœ(˜(Jšœ(˜(Jšœ˜Jšœ œ˜—J˜—šž œœœ œ˜@š œœœœœ(˜@Jšœœ*˜5—J˜—š ž œœ œœ œ˜8Jšœœ$˜+J˜—šžœœ ˜$Jšœ œœ˜šœœœ ˜Jšœ"œžœœ˜J—J˜—šžœœœ˜6šœœœ˜Jšœœ#˜-Jšœœœœ˜.Jšœ;œ˜E—J˜—šžœœœ™Ašœœœ™šžœœ ™Jšœœ*™;—Jšœœœ™Jšœœ#™-Jšœœ,™EJšœœ<™IJšœœžœœ™N—J™—šžœœ œ˜Dšœœœœ˜-Jšœ™—Jšœœœ˜*Jšœœœœœœœœ˜OJšœœœ˜4šžœœœ˜'Jšœœœ ˜Jšœœœœ˜š œœœ œ œ˜GJšœ$˜$šœ!˜'Jšœ=œœ˜\—Jšœ˜—š œœœ œ œ˜GJšœ$˜$šœœœ˜ šœ˜%š œœœ!œœ˜Ašœ&œ˜.Jšœ5˜5Jšœ/˜/Jšœ œœ˜*—Jšœ˜——Jšœ˜—Jšœœœœ˜"——Jšœ7˜7Jšœ˜Jšœœ(˜Bšœ œœ*˜>JšœœCœ˜W—šœ1œœ˜EJšœœœ˜3—Jš œ œœœœœ˜Fšœ œœ˜*šœœœ˜&Jšœ'œœ˜1Jšžœ˜/Jšžœ˜/Jš œœœœœ˜&—Jšœ˜—Jšž™šœ œ œ˜5šœœœ˜&Jšœ%œœ˜1šœœœ6˜FJš œœœ œ ˜8—Jšœ˜5——Jšœ ˜0Jš œœœ'œ ˜RJšœ ˜1Jšœœ ˜6š œœœ œœ˜Bšœœœ˜0Jšœœœ˜#Jšœœœœ˜5——J˜—šž œœœœœœœ˜RJš œœœœœœœ˜VJ˜—šž œœœœ ˜?šœœœ˜"Jšœœœœ˜0Jšœ˜ —J˜—š ž œœœ œœœ ˜SJšœœ˜Jšœœœœ ˜Jšœœœœ˜š œœœœ œ˜œ˜DJšœ4œ˜:Jšœ2œ˜9Jšœ6œ˜œ˜DJšœ3œ˜:Jšœ4œ˜;Jšœ1œ˜7Jšœ1œ˜8Jšœ1œ˜7Jšœ6œ˜—J˜—Jšœ˜——…—aœ‡«