DIRECTORY Core, CoreFrame, CoreGlue, CoreName, CoreOps, CoreProperties, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, REFBit, Rope; IFUCoreCtlImpl: CEDAR PROGRAM IMPORTS CoreFrame, CoreGlue, CoreName, CoreOps, CoreProperties, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, REFBit, Rope EXPORTS IFUCoreCtl = BEGIN ROPE: TYPE = Core.ROPE; CellType: TYPE = Core.CellType; Wire: TYPE = Core.Wire; SigRec: TYPE = CoreName.SigRec; Section: TYPE = IFUCoreCtl.Section; PLASection: TYPE = IFUCoreCtl.PLASection; PLASectionRec: TYPE = IFUCoreCtl.PLASectionRec; PLADescription: TYPE = IFUCoreCtl.PLADescription; XsFormSeqRec: TYPE = IFUCoreCtl.XsFormSeqRec; PublicRefRec: TYPE = IFUCoreCtl.PublicRefRec; XlatePubSeqRec: TYPE = IFUCoreCtl.XlatePubSeqRec; PLAType: TYPE = IFUCoreDrive.PLAType; Drive: TYPE = IFUCoreDrive.Drive; DriveRec: TYPE = IFUCoreDrive.DriveRec; RowType: TYPE = IFUCoreDrive.RowType; Dir: TYPE = IFUCoreDrive.Dir; DrGate: TYPE = IFUCoreDrive.DrGate; Ph: TYPE = IFUCoreDrive.Ph; Polarity: TYPE = IFUCoreDrive.Polarity; Signal: SIGNAL = CODE; ctlCellClass: PUBLIC Core.CellClass _ CoreOps.SetClassPrintProc[ NEW[Core.CellClassRec _ [name: "IFUCoreCtl", recast: NIL]], ClassPrintProc]; ClassPrintProc: CoreOps.PrintClassProc = { ref: PLASection _ NARROW[data]; out.PutF["\nControl: ", IO.rope[ ref.desc.name ] ] }; CellProc: PUBLIC PROC [ section: Section, desc: PLADescription ] RETURNS [cellType: Core.CellType] = { -- ctlCellClass SELECT section FROM complete => { name: ROPE _ desc.name.Cat["Cmpl"]; cellType _ CoreFrame.NewFrameCells[name: name, rec: [first: top], cells: LIST[ CellProc[outSec, desc ], CellProc[inSec, desc ] ] ] }; outSec => { name: ROPE _ desc.name.Cat["OutSec"]; cellType _ CoreFrame.NewFrameCells[name: name, rec: [first: left], cells: LIST[ CellProc[outBody, desc ], CellProc[outDr, desc ] ] ] }; inSec => { name: ROPE _ desc.name.Cat["InSec"]; desc.includeIns _ TRUE; cellType _ CoreFrame.NewFrameCells[name: name, rec: [first: left], cells: LIST[ CellProc[inSB, desc ], CellProc[inDr, desc ] ] ] }; ENDCASE => { name: ROPE _ SELECT section FROM outBody => desc.name.Cat["OutBody"], outDr => desc.name.Cat["OutDr"], inSB => desc.name.Cat["InSB"], inDr => desc.name.Cat["InDr"], ENDCASE => ERROR; cellType _ CoreOps.SetCellTypeName[ NEW [ Core.CellTypeRec _ [ class: ctlCellClass, public: CoreOps.CreateWires[0], data: NEW[PLASectionRec _ [desc: desc, section: section] ] ] ], name]; CoreFrame.SetFrameExpandProc[soft, cellType, NEW[CoreFrame.ExpandProc_ Expand]]; CoreFrame.SetFrameExpandProc[hard, cellType,NEW[CoreFrame.ExpandProc_Expand]]}}; Expand: CoreFrame.ExpandProc = { secRec: PLASection _ NARROW[frameCT.data]; MakePLA[secRec.desc]; SELECT secRec.section FROM inDr => {CoreFrame.Expand[hard, secRec.desc.inDrCT]; frameCT^ _ secRec.desc.inDrCT^}; outDr => {CoreFrame.Expand[hard, secRec.desc.outDrCT]; frameCT^ _ secRec.desc.outDrCT^}; inSB => {CoreFrame.Expand[hard, secRec.desc.inSBCT]; frameCT^ _ secRec.desc.inSBCT^}; outBody => { frameCT^ _ secRec.desc.outBodyCT^}; ENDCASE => Signal[]; CoreFrame.SetFrameExpandProc[soft, frameCT, NIL]; CoreFrame.SetFrameExpandProc[hard, frameCT, NIL] }; MakePLA: PUBLIC PROC [desc: PLADescription] = { MakePLA1[desc]; MakePLA2[desc]}; MakePLA1: PUBLIC PROC [desc: PLADescription] = { OPEN desc; bitForm: REFBit.Format; IF valid THEN RETURN; IF plaType=precharged AND termsPerHeader=1000 THEN termsPerHeader_20; IF ttt=NIL THEN ttt _ PLAOps.ReadPLAFile[name.Cat[".ttt"], log]; bitForm _ REFBit.Desc[ttt.data].bitForm; FOR bit: INT DECREASING IN [0..bitForm.size) DO bitForm[bit].name _ CoreName.BitRopeToSigRope[bitForm[bit].name]; bitForm[bit].nameInv _ CoreName.BitRopeToSigRope[bitForm[bit].nameInv]; ENDLOOP; bitForm _ REFBit.Desc[ttt.out].bitForm; FOR bit: INT DECREASING IN [0..bitForm.size) DO bitForm[bit].name _ CoreName.BitRopeToSigRope[bitForm[bit].name]; bitForm[bit].nameInv _ CoreName.BitRopeToSigRope[bitForm[bit].nameInv]; ENDLOOP; IF inDrs=NIL THEN { initial: IFUCoreDrive.DriveRec _ [ drDir: in, dualOut: TRUE, in: [pos, plaPhs[drIn] ], ref: [pos, plaPhs[drInClk] ], out: [pos, plaPhs[plaIn] ] ]; inDrs _ IFUCoreDrive.RefToDrives[ttt.data, initial]}; IF outDrs=NIL THEN { initial: IFUCoreDrive.DriveRec _ [ drDir: out, in: [ pol: SELECT desc.plaType FROM precharged, hot=>neg ENDCASE=>pos, ph: plaPhs[drOutClk] ], ref: [pos, plaPhs[drOutClk] ], out: [pos, plaPhs[drOut] ], plaType: desc.plaType, fire: desc.fire, fireV: desc.fireV, nPreChg: desc.nPreChg ]; outDrs _ IFUCoreDrive.RefToDrives[ttt.out, initial]} }; MakePLA2: PUBLIC PROC [desc: PLADescription] = { OPEN desc; IF valid THEN RETURN; IF plaInNames=NIL THEN { FOR list: IFUCoreDrive.Drives _ inDrs, list.rest WHILE list#NIL DO IF list.first.drRowType#conn THEN LOOP; plaInNames _ CONS[IFUCoreDrive.DriveName[list.first, out], plaInNames]; plaInNames _ CONS[IFUCoreDrive.DriveName[list.first, nout], plaInNames] ENDLOOP; plaInNames _ Lists.ReverseList[plaInNames]}; IF plaOutNames=NIL THEN { FOR list: IFUCoreDrive.Drives _ outDrs, list.rest WHILE list#NIL DO IF list.first.drRowType#conn THEN LOOP; plaOutNames _ CONS[IFUCoreDrive.DriveName[list.first, in], plaOutNames] ENDLOOP; plaOutNames _ Lists.ReverseList[plaOutNames]}; IF drSignalOrder=NIL THEN { FOR list: IFUCoreDrive.Drives _ outDrs, list.rest WHILE list#NIL DO IF list.first.drRowType#conn THEN LOOP; drSignalOrder _ CONS[IFUCoreDrive.DriveName[list.first, in], drSignalOrder] ENDLOOP; drSignalOrder _ Lists.ReverseList[drSignalOrder]}; BuildConnTranslationArray[desc]; SELECT plaType FROM hot => IFUCoreCtl.MakeHotPLA[desc]; precharged => IFUCoreCtl.MakePreChargedPLA[desc]; ENDCASE => ERROR; outSh _ inSh; IF includeIns THEN outSh _ IFUCoreDrive.ConnectDrives[inDrs, outSh]; outSh _ IFUCoreDrive.ConnectDrives[outDrs, outSh]; IF desc.inSBCT =NIL THEN desc.inSBCT _ CoreGlue.CellProc[t: conn, r: conn]; IF desc.inDrCT =NIL THEN desc.inDrCT _ IFUCoreDrive.DrivesToFrame[desc.name.Cat["InDr"], desc.inDrs]; IF desc.outDrCT =NIL THEN desc.outDrCT _ IFUCoreDrive.DrivesToFrame[desc.name.Cat["OutDr"], desc.outDrs]; valid _ TRUE}; ifuCoreCtlPLADesc: ATOM = CoreProperties.RegisterProperty[prop: $IFUCoreCtlPLADesc]; gnd: NAT _ 0; GND: ROPE _ CoreName.RopeNm["GND"]; vdd: NAT _ 1; VDD: ROPE _ CoreName.RopeNm["VDD"]; in: NAT _ 2; out: NAT _ 3; BuildConnTranslationArray: PROC [desc: PLADescription ] = { index: INT _ -1; smlOutNames: LIST OF ROPE; log.PutRope["\n Building pla translation array"]; desc.connSeq _ NEW[IFUCoreCtl.ConnSeq[Lists.ListLength[desc.drSignalOrder]]]; FOR list: LIST OF ROPE _ desc.drSignalOrder, list.rest WHILE list#NIL DO pos: INT _ Lists.ListItemIndex[desc.plaInNames, list.first]; index _ index+1; IF pos#-1 THEN { desc.connSeq[index] _ [index: pos/2, isOutput: FALSE, isLeftSide: (pos MOD 2 = 0)]; LOOP}; pos _ Lists.ListItemIndex[desc.plaOutNames, list.first]; IF pos=-1 THEN ERROR; -- Signal name not found; smlOutNames _ CONS[list.first, smlOutNames]; desc.connSeq[index] _ [index: pos, isOutput: TRUE, isLeftSide: FALSE]; ENDLOOP; smlOutNames _ Lists.ReverseList[smlOutNames]; desc.smlToBigOut _ NEW[IFUCoreCtl.XsFormSeqRec[Lists.ListLength[smlOutNames]]]; FOR i: CARDINAL IN [0..desc.smlToBigOut.size) DO desc.smlToBigOut[i] _ Lists.ListItemIndex[desc.plaOutNames, Lists.ListIndexItem[smlOutNames, i]] ENDLOOP; desc.plaOutNames _ smlOutNames; FOR index: INT IN [0..desc.connSeq.size) DO desc.connSeq[index].dr _ desc.outDrs.first; desc.outDrs _ desc.outDrs.rest ENDLOOP; IF desc.outDrs#NIL THEN Signal}; log: IO.STREAM _ CoreFrame.GetLog[]; END. !ήIFUCoreCtlImpl.mesa, Copyright c 1986 by Xerox Corporation. All rights reserved. Last Edited by Curry, October 21, 1986 8:51:28 pm PDT Don Curry October 30, 1986 9:45:11 am PST IF plaInNames=NIL THEN { inForm: REFBit.Format _ REFBit.Desc[ttt.data].bitForm; FOR i: CARDINAL DECREASING IN [0..inForm.size) DO sig: SigRec _ CoreName.NameSig[inForm[i].name]; sigI: SigRec _ CoreName.NameSig[inForm[i].nameInv]; name: ROPE _ IF sig.root#NIL THEN inForm[i].name ELSE plaInNames _ CONS[ Select [[TRUE, inForm[i].name, inForm[i].nameInv, plaPhs[plaIn]]], plaInNames]; plaInNames _ CONS[ CoreName.SignalName [FALSE, inForm[i].name, inForm[i].nameInv, plaPhs[plaIn]], plaInNames]; ENDLOOP}; IF plaOutNames=NIL THEN { outForm: REFBit.Format _ REFBit.Desc[ttt.out].bitForm; FOR i: CARDINAL DECREASING IN [0..outForm.size) DO plaOutNames _ CONS[ CoreName.SignalName [FALSE, outForm[i].name, outForm[i].nameInv, plaPhs[drOut]], plaOutNames]; ENDLOOP}; IF drSignalOrder=NIL THEN { outForm: REFBit.Format _ REFBit.Desc[ttt.out].bitForm; FOR i: CARDINAL DECREASING IN [0..outForm.size) DO drSignalOrder _ CONS[ CoreName.SignalName [FALSE, outForm[i].name, outForm[i].nameInv, plaPhs[drOut]], drSignalOrder]; ENDLOOP}; ENDCASE => IFUCoreCtl.MakeStaticPLA[desc]; RegisterSimulationProcs[desc]; FormatSignalName: PROC[format: REFBit.Format, bit: INT, not: BOOL, ph: Ph] RETURNS[signal: ROPE] = { name, nameInv: ROPE; dual, inverted: BOOL; cy, idx: INT; [name, nameInv, dual, inverted, cy, idx] _ CoreName.NormalFormatNames[format[bit]]; Ok, This proc should probably be using something in desc (they are ordered by fromat) rather than the format; IF inverted THEN drive.in.pol _ SELECT drive.in.pol FROM pos=>neg, neg=>pos, ENDCASE=>ERROR; [inv, name] _ CoreName.SelectName[(relSig.pol=neg)#inv, drive.name, drive.nameInv]; name _ CoreName.SigName[[inv, name, relSig.ph, drive.cy, drive.idx]]}; signal _ CoreName.RopeNm[ CoreName.NormalFormatNames[format[bit]]; [not, format[bit].name, format[bit].nameInv, ph]] }; RegisterSimulationProcs: PROC[desc: PLADescription] = { gnd: INT _ 0; vdd: INT _ 0; inCnt: INT _ 0; outCnt: INT _ 0; recCell: CellType _ CoreFrame.FCT[desc.outBodyCT].cell; inForm: REFBit.Format _ REFBit.Desc[desc.ttt.data].bitForm; outForm: REFBit.Format _ REFBit.Desc[desc.ttt.out].bitForm; table: HashTable.Table _ HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]; FOR bit: INT IN [0..inForm.size) DO name: ROPE _ FormatSignalName[inForm, bit, FALSE, desc.plaPhs[plaIn]]; nameInv: ROPE _ FormatSignalName[inForm, bit, TRUE, desc.plaPhs[plaIn]]; [ ] _ HashTable.Store[table, name, NEW[PublicRefRec _ [in, FALSE, bit]]]; [ ] _ HashTable.Store[table, nameInv, NEW[PublicRefRec _ [in, TRUE, bit]]]; inCnt _ inCnt + 2 ENDLOOP; FOR bit: INT IN [0..outForm.size) DO name: ROPE _ FormatSignalName[outForm, bit, FALSE, desc.plaPhs[drOutClk]]; nameInv: ROPE _ FormatSignalName[outForm, bit, TRUE, desc.plaPhs[drOutClk]]; IF desc.plaType=precharged THEN [] _ HashTable.Store[table, nameInv, NEW[PublicRefRec _ [in, TRUE, bit]]] ELSE [] _ HashTable.Store[table, name, NEW[PublicRefRec _ [in, FALSE, bit]]]; outCnt _ outCnt + 1 ENDLOOP; desc.xlatePublic _ NEW[XlatePubSeqRec[recCell.public.size]]; IF recCell.public.size # inCnt + outCnt + 2 THEN Signal[]; FOR pub: NAT IN [0..recCell.public.size) DO wireNm: ROPE _ CoreName.WireNm[recCell.public[pub]].n; ref: REF PublicRefRec; SELECT wireNm FROM GND => {ref_NIL; gnd _ pub; LOOP}; VDD => {ref_NIL; vdd _ pub; LOOP}; ENDCASE => { ref _ NARROW[HashTable.Fetch[table, wireNm].value]; IF ref=NIL THEN Signal[]}; desc.xlatePublic[pub] _ ref; ENDLOOP; [] _ Ports.InitPort[wire: recCell.public[gnd]]; [] _ Ports.InitPort[wire: recCell.public[vdd]]; [] _ Rosemary.SetFixedWire[recCell.public[vdd], H]; [] _ Rosemary.SetFixedWire[recCell.public[gnd], L]; FOR pub: NAT IN [0..recCell.public.size) DO IF desc.xlatePublic[pub]#NIL THEN IF desc.xlatePublic[pub].dir=in THEN [] _ Ports.InitPort[wire: recCell.public[pub], initType: b, initDrive: none] ELSE [] _ Ports.InitPort[wire: recCell.public[pub], initType: b, initDrive: drive]; ENDLOOP; [] _ Rosemary.BindCellType[ cellType: recCell, roseClassName: Rosemary.Register[ roseClassName: desc.name.Cat["Sim"], init: PLAInitProc, evalSimple: PLAEvalProc] ]; CoreProperties.PutCellTypeProp[on: recCell, prop: ifuCoreCtlPLADesc, value: desc]; [] _ Rosemary.AddCutSets[cellType: recCell, cs1: "JustAboveTransistors"]}; PLAInitProc: Rosemary.InitProc ~ {RETURN[CoreProperties.GetCellTypeProp[from: cellType, prop: ifuCoreCtlPLADesc]]}; PLAEvalProc: Rosemary.EvalProc ~ { desc: PLADescription _ NARROW[stateAny]; inForm: REFBit.Format _ REFBit.Desc[desc.ttt.data].bitForm; outForm: REFBit.Format _ REFBit.Desc[desc.ttt.out].bitForm; allUndefined: BOOL _ p[vdd].l#H OR p[gnd].l#L; FOR pub: INT IN [0..p.size) DO ref: REF PublicRefRec _ desc.xlatePublic[pub]; IF ref#NIL AND ref.dir=in THEN IF ref.inverted THEN REFBit.Set[desc.ttt.data, ref.index, ~p[pub].b] ELSE REFBit.Set[desc.ttt.data, ref.index, p[pub].b]; ENDLOOP; PLAOps.GetOutForData[desc.ttt]; FOR pub: INT IN [0..p.size) DO ref: REF PublicRefRec _ desc.xlatePublic[pub]; IF ref#NIL AND ref.dir=out THEN IF ref.inverted THEN p[pub].b _ NOT REFBit.Get[desc.ttt.out, ref.index] ELSE p[pub].b _ REFBit.Get[desc.ttt.out, ref.index]; ENDLOOP }; RegisterSimulationProcs: PROC[desc: PLADescription] = { IndexNames: TYPE = RECORD[index: NAT, name, nameInv: ROPE]; list: LIST OF IndexNames; cnt: NAT _ 0; recCell: CellType _ CoreFrame.FCT[desc.outBodyCT].cell; newPub: Core.Wires; intOnly: Core.Wires; inForm: REFBit.Format _ REFBit.Desc[desc.ttt.data].bitForm; outForm: REFBit.Format _ REFBit.Desc[desc.ttt.out].bitForm; FOR bit: NAT DECREASING IN [0..inForm.size) DO name: ROPE _ FormatSignalName[inForm, bit, FALSE, desc.plaPhs[plaIn]]; nameInv: ROPE _ FormatSignalName[inForm, bit, TRUE, desc.plaPhs[plaIn]]; root: ROPE _ IF inForm[bit].name#NIL THEN inForm[bit].name ELSE inForm[bit].nameInv; IF IFUCoreDrive.FindDrive[root, desc.inDrs] = NIL THEN Signal[] ELSE {cnt _ cnt + 1; list _ CONS[[bit, name, nameInv], list]}; cnt _ cnt + 1; list _ CONS[[bit, name, nameInv], list]; ENDLOOP; desc.xlateIn _ NEW[XsFormSeqRec[cnt]]; FOR bit: NAT DECREASING IN [0..cnt) DO desc.xlateIn[bit] _ list.first.index; newPub _ CONS[CoreOps.CreateWires[0, list.first.name], newPub]; newPub _ CONS[CoreOps.CreateWires[0, list.first.nameInv], newPub]; list _ list.rest; ENDLOOP; list_NIL; cnt _ 0; FOR bit: NAT DECREASING IN [0..outForm.size) DO name: ROPE _ FormatSignalName[outForm, bit, FALSE, desc.plaPhs[drOutClk]]; nameInv: ROPE _ FormatSignalName[outForm, bit, TRUE, desc.plaPhs[drOutClk]]; root: ROPE _ IF outForm[bit].name#NIL THEN outForm[bit].name ELSE outForm[bit].nameInv; IF IFUCoreDrive.FindDrive[root, desc.outDrs] = NIL THEN Signal[] ELSE {cnt _ cnt + 1; list _ CONS[[bit, name, nameInv], list]}; ENDLOOP; desc.xlateOut _ NEW[XsFormSeqRec[cnt]]; FOR bit: NAT DECREASING IN [0..cnt) DO desc.xlateOut[bit] _ list.first.index; IF desc.plaType=precharged THEN { newPub _ CONS[CoreOps.CreateWires[0, list.first.nameInv], newPub]; intOnly _ CONS[CoreOps.CreateWires[0, list.first.name], intOnly]} ELSE { newPub _ CONS[CoreOps.CreateWires[0, list.first.name], newPub]; intOnly _ CONS[CoreOps.CreateWires[0, list.first.nameInv], intOnly]}; list _ list.rest; ENDLOOP; newPub _ CONS[CoreOps.CreateWires[0, GND], newPub]; newPub _ CONS[CoreOps.CreateWires[0, VDD], newPub]; recCell _ CoreCreate.Cell[ public: CoreOps.CreateWire[newPub], onlyInternal: CoreOps.CreateWire[intOnly], instances: LIST[ CoreCreate.Instance[recCell]] ]; CoreBlock.PutCellSide[recCell, left]; CoreBlock.MergeSides[recCell]; PWC.SetAbutX[recCell]; [] _ Ports.InitPort[wire: recCell.public[gnd], initType: l]; [] _ Ports.InitPort[wire: recCell.public[vdd], initType: l]; [] _ Ports.InitPort[wire: recCell.public[in], initType: composite]; [] _ Ports.InitPort[wire: recCell.public[out], initType: composite, initDrive: drive]; FOR bit: NAT IN [0..recCell.public[in].size) DO [] _ Ports.InitPort[wire: recCell.public[in][bit], initType: l] ENDLOOP; FOR bit: NAT IN [0..recCell.public[out].size) DO [] _ Ports.InitPort[wire: recCell.public[out][bit], initType: l, initDrive: drive] ENDLOOP; [] _ Rosemary.BindCellType[ cellType: recCell, roseClassName: Rosemary.Register[ roseClassName: desc.name.Cat["Sim"], init: PLAInitProc, evalSimple: PLAEvalProc] ]; CoreProperties.PutCellTypeProp[on: recCell, prop: ifuCoreCtlPLADesc, value: desc]; [] _ Rosemary.AddCutSets[cellType: recCell, cs1: "JustAboveTransistors"]}; desc.connSeq will contain indexes relative to the big (original) PLA ΚP˜šœ™Jšœ<™—Jšœœ™7Jšœ™—Jšœœ  œ™&š œœ œœ ™&Jšœ%™%Jšœ œ3™BJšœ œ5™DJšœ™Jšœ™—Jšœœ ™š œœ œœ™/Jšœœ"œ™KJšœ œ"œ™Lšœœœ™&Jšœ™Jšœ™—šœ-™2Jšœ ™ Jšœœ™>—Jšœ™—Jšœœ  œ™(š œœ œœ ™&Jšœ&™&šœ™šœ™Jšœ œ6™CJšœ œ5™C—šœ™Jšœ œ4™AJšœ œ8™F——Jšœ™Jšœ™—Jšœ œœ ™3Jšœ œœ ™3J™™Jšœ$™$Jšœ*™*Jšœ œ"™2—Jšœ%™%Jšœ™Jšœ™J™Jšœ<™