<> <> <> <> <<>> <> DIRECTORY Buttons USING [Create, ReLabel, ButtonProc, Button, SetDisplayStyle], Containers USING [Container, Create], CD USING [ Design, Instance, Object], CDCommandOps USING [RegisterWithMenu], CDOps USING [SelectedInstance], CDProperties USING [PutDesignProp], CDSequencer USING [Command], Core USING [CellType, Wire], CoreFlat USING [FlatWire, FlatWireRec, rootCellType, PathError], CoreOps USING [GetCellTypeName, VisitRootAtomics], HashTable USING [Fetch, Table], Icons USING [NewIconFromFile], ImagerFont USING [Font, Find], IO USING [PutF, real], Menus USING [MenuProc, CreateEntry, AppendMenuEntry, CreateMenu, Menu], Mint, PWCore USING [Layout, CorrespondingCellType, LayoutCellTypeInfo], Rope USING [ROPE, Cat, Replace], Sisyph USING [mode], Sinix USING [Mode], SinixOps, TerminalIO USING [PutRope, PutF], ViewerOps USING [DestroyViewer, OpenIcon], WriteCapa; CDMint: CEDAR MONITOR IMPORTS Buttons, Containers, CoreFlat, CDCommandOps, CDOps, CDProperties, CoreOps, Icons, IO, HashTable, ImagerFont, Menus, Mint, PWCore, Rope, Sisyph, SinixOps, TerminalIO, ViewerOps, WriteCapa ~ BEGIN Key: TYPE = REF KeyRec; KeyRec: TYPE = RECORD [ locked: BOOL _ TRUE, unlocked: CONDITION ]; debugCircuit: Mint.Circuit; verbose: BOOLEAN _ FALSE; maxNumber: NAT _ 10; nOfPaths: CARD _ 16; buttonFont: ImagerFont.Font _ ImagerFont.Find["Xerox/TiogaFonts/Gacha10"]; defaultCapa: REAL _ 0.5; vdd: REAL _ 5.0; vTn: REAL _ 0.78; vbb: REAL _ 1200.0; --mV SetButtonToL: PROC [button: Buttons.Button] ~ { Buttons.SetDisplayStyle[button, $WhiteOnBlack, FALSE]; Buttons.ReLabel[button, Rope.Replace[button.name, 0, 1, "L"]]; }; SetButtonToX: PROC [button: Buttons.Button] ~ { Buttons.SetDisplayStyle[button, $BlackOnWhite, FALSE]; Buttons.ReLabel[button, Rope.Replace[button.name, 0, 1, "X"]]; }; SetButtonToH: PROC [button: Buttons.Button] ~ { Buttons.SetDisplayStyle[button, $WhiteOnBlack, FALSE]; Buttons.ReLabel[button, Rope.Replace[button.name, 0, 1, "H"]]; }; SetNewVal: Buttons.ButtonProc ~ { <> button: Buttons.Button _ NARROW[parent]; node: Mint.Node _ NARROW[clientData]; SELECT mouseButton FROM red => { Mint.SetNode[node: node, val: FALSE]; SetButtonToL[button]; }; yellow => { node.history _ NIL; SetButtonToX[button]; }; blue => { Mint.SetNode[node: node, val: TRUE]; SetButtonToH[button]; }; ENDCASE => ERROR; }; MakeMintPanelViewer: PROC [circuit: Mint.Circuit] RETURNS [modifList: Mint.NodeList] ~ { EachWireButton: PROC [wire: Core.Wire] ~ { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: CoreFlat.rootCellType, wireRoot: public, wire: wire ]]; node: Mint.Node _ NARROW[HashTable.Fetch[circuit.nodeTable, flatWire].value]; button: Buttons.Button _ Buttons.Create[ info: [ name: Rope.Cat["X : ", Mint.RopeFromNode[node, circuit]], parent: container, wx: entryVSpace, wy: height + 2, border: TRUE ], proc: SetNewVal, clientData: node, fork: FALSE, font: buttonFont, paint: FALSE]; IF node.history#NIL THEN IF Mint.GetNode[node] THEN SetButtonToH[button] ELSE SetButtonToL[button]; height _ height + button.wh + entryVSpace; }; EachWireCheck: PROC [wire: Core.Wire] ~ { flatWire: CoreFlat.FlatWire _ NEW[CoreFlat.FlatWireRec _ [ flatCell: CoreFlat.rootCellType, wireRoot: public, wire: wire ]]; node: Mint.Node _ NARROW[HashTable.Fetch[circuit.nodeTable, flatWire].value]; IF node.history#NIL THEN modifList _ CONS[node, modifList]; }; entryHeight: CARDINAL = 12; entryVSpace: CARDINAL = 6; height: CARDINAL _ 0; name: Rope.ROPE _ CoreOps.GetCellTypeName[circuit.rootCell]; key: Key _ NEW[KeyRec]; menu: Menus.Menu _ MakePanelMenu[key]; container: Containers.Container _ Containers.Create[ info: [ name: IF name=NIL THEN "MintPanel" ELSE name, menu: menu, iconic: TRUE, icon: Icons.NewIconFromFile["/DATools/DATools6.1/Mint/Mint.icons", 1], column: left, scrollable: TRUE, inhibitDestroy: TRUE ], paint: FALSE ]; height _ entryVSpace; CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: EachWireButton]; ViewerOps.OpenIcon[container]; WaitForOk[key]; CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: EachWireCheck]; ViewerOps.DestroyViewer[container]; }; -- MakeMintPanelViewer MakePanelMenu: PROC [key: Key] RETURNS [menu: Menus.Menu] ~ { menu _ Menus.CreateMenu[]; Menus.AppendMenuEntry[ menu: menu, entry: Menus.CreateEntry[ name: "OK", proc: OK, clientData: key, guarded: FALSE, documentation: "Fake"] ]; }; WaitForOk: ENTRY PROC [key: Key] ~ { ENABLE UNWIND => NULL; WHILE key.locked DO WAIT key.unlocked ENDLOOP; }; OK: ENTRY Menus.MenuProc ~ { <> ENABLE UNWIND => NULL; key: Key _ NARROW[clientData]; key.locked _ FALSE; BROADCAST key.unlocked; }; GetLayoutExtracted: PUBLIC PROC [schCT: Core.CellType] RETURNS [maskCT: Core.CellType, extractedToSource: HashTable.Table] ~ { indirectObj: CD.Object = PWCore.Layout[schCT]; layoutCellType: Core.CellType = PWCore.CorrespondingCellType[indirectObj]; source: Core.CellType; [sourceCellType: source, extractedCellType: maskCT, extractedToSource: extractedToSource] _ PWCore.LayoutCellTypeInfo[layoutCellType]; }; CorrectROn: PROC [fet: Mint.Fet, vBias: REAL, biasedList: LIST OF Mint.FetType] ~ { alpha: REAL; fType: Mint.FetType; FOR fTList: LIST OF Mint.FetType _ biasedList, fTList.rest UNTIL fTList=NIL DO IF fTList.first.l#fet.type.l THEN LOOP; IF fTList.first.w#fet.type.w THEN LOOP; IF fTList.first.type#fet.type.type THEN LOOP; fet.type _ fTList.first; RETURN; ENDLOOP; fType _ NEW[Mint.FetTypeRec _ fet.type^]; alpha _ SELECT fType.type FROM pE => ERROR, nE => (vBias-vTn)/(vdd-vTn), ENDCASE => ERROR; fType.rOnInv _ IF alpha>0.0 THEN fet.type.rOnInv*alpha ELSE 0.0; fet.type _ fType; }; BiasFets: PROC [node: Mint.Node] RETURNS [numberOfModifications: CARD _ 0] ~ { bList: LIST OF Mint.FetType _ NIL; vBias: REAL _ Mint.SettledValuesOfNode[node].v; FOR i: NAT IN [0..node.fetSeq.nUsed) DO fet: Mint.Fet = node.fetSeq[i]; IF fet.gate=node THEN { CorrectROn[fet, vBias, bList]; numberOfModifications _ numberOfModifications+1 } ENDLOOP; }; ExtractAndPrepare: PROC [mode: Sinix.Mode, comm: CDSequencer.Command] RETURNS[circuit: Mint.Circuit, instance: CD.Instance] ~ { coreCell: Core.CellType; isLayout: BOOLEAN _ mode#Sisyph.mode; gndNode, vddNode, vbbNode: Mint.Node; fixedV: Mint.NodeList; multiple: BOOL; isVbb: BOOL _ TRUE; [instance, multiple] _ CDOps.SelectedInstance[comm.design]; IF instance=NIL THEN {TerminalIO.PutRope["*** No current selection--can't do it.\n"]; RETURN}; IF multiple THEN TerminalIO.PutRope["*** Multiple instances selected--Using first.\n"]; IF mode=NIL THEN {TerminalIO.PutRope ["technology unknown.\n"]; RETURN}; coreCell _ NARROW[SinixOps.ExtractCDInstance [instance, comm.design, mode].result]; IF isLayout THEN WriteCapa.WriteWireCapa[coreCell, comm.design.technology.key]; circuit _ Mint.CreateCircuit[coreCell]; vddNode _ Mint.NodeFromRope["public.Vdd", circuit]; Mint.SetNode[vddNode, TRUE]; gndNode _ Mint.NodeFromRope["public.Gnd", circuit]; Mint.SetNode[gndNode, FALSE]; vbbNode _ Mint.NodeFromRope["public.Vbb", circuit ! CoreFlat.PathError => {isVbb _ FALSE; CONTINUE}]; IF isVbb THEN { TerminalIO.PutF["Vbb found and set to %4.1f\n", IO.real[vbb]]; Mint.EditNodeHistory[vbbNode, 0.0, vbb]; [] _ BiasFets[vbbNode]; fixedV _ LIST[gndNode, vddNode, vbbNode]; } ELSE { fixedV _ LIST[gndNode, vddNode]; }; Mint.InputData[circuit, fixedV, isLayout, defaultCapa]; }; ShowCamino: PROC [decoration: SinixOps.Decoration, design: CD.Design, instance: CD.Instance, root: Core.CellType, camino: Mint.Camino] ~ { flatWires: LIST OF SinixOps.FlatWireRec _ NIL; FOR iCaminoData: LIST OF Mint.CaminoCell _ camino.data, iCaminoData.rest UNTIL iCaminoData.rest=NIL DO flatWires _ CONS[iCaminoData.first.node.flatWire^, flatWires]; ENDLOOP; SinixOps.HighlightNets[decoration, design, instance, root, flatWires]; }; ExtractAndTiming: PROC [mode: Sinix.Mode, comm: CDSequencer.Command] ~ { worst: Mint.ps; caminos: Mint.Caminos; circuit: Mint.Circuit; clkList: Mint.NodeList; instance: CD.Instance; warningMsg: Rope.ROPE _ NIL; [circuit, instance] _ ExtractAndPrepare[mode, comm]; IF circuit=NIL THEN RETURN; clkList _ LIST[ Mint.NodeFromRope[clkName, circuit ! CoreFlat.PathError => {warningMsg _ Rope.Cat["warning: no ", clkName, " wire"]; CONTINUE}]]; IF warningMsg#NIL THEN clkList _ MakeMintPanelViewer[circuit]; [worst, caminos] _ Mint.MaxFreqEvaluate[circuit, clkList, nOfPaths, 0.0]; IO.PutF[Mint.StdOut, "longest time: %4.1fns\n", IO.real[worst/1000.0]]; Mint.PrintCamino[caminos.first, circuit]; ShowCamino[mode.decoration, comm.design, instance, circuit.rootCell, caminos.first]; Mint.KillCircuit[circuit]; }; ExtractAndCheck: PROC [mode: Sinix.Mode, comm: CDSequencer.Command] ~ { circuit: Mint.Circuit _ ExtractAndPrepare[mode, comm].circuit; IF circuit=NIL THEN RETURN; Mint.CheckLibrary[circuit]; debugCircuit _ circuit; }; ExtractAndMint: PROC [mode: Sinix.Mode, comm: CDSequencer.Command] ~ { circuit: Mint.Circuit _ ExtractAndPrepare[mode, comm].circuit; IF circuit=NIL THEN RETURN; IF verbose THEN Mint.OutputResults[circuit]; [] _ Mint.InteractiveSimulate[circuit]; debugCircuit _ circuit; }; TimingFromLayout: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; mode: Sinix.Mode _ SinixOps.GetExtractMode[comm.design.technology]; TerminalIO.PutRope ["TimingLayout\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndTiming[mode, comm]; TerminalIO.PutRope ["Timing finished.\n"]; }; TimingFromSchematics: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; TerminalIO.PutRope ["TimingSchematics\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndTiming[Sisyph.mode, comm]; TerminalIO.PutRope ["Timing finished.\n"]; }; CheckFromLayout: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; mode: Sinix.Mode _ SinixOps.GetExtractMode[comm.design.technology]; TerminalIO.PutRope ["CheckLayout\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndCheck[mode, comm]; TerminalIO.PutRope ["Check finished.\n"]; }; CheckFromSchematics: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; TerminalIO.PutRope ["CheckSchematics\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndCheck[Sisyph.mode, comm]; TerminalIO.PutRope ["Check finished.\n"]; }; MintFromLayout: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; mode: Sinix.Mode _ SinixOps.GetExtractMode[comm.design.technology]; TerminalIO.PutRope ["MintLayout\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndMint[mode, comm]; TerminalIO.PutRope ["Mint finished.\n"]; }; MintFromSchematics: PROC [comm: CDSequencer.Command] ~ { <> abort: REF BOOL _ NEW [BOOL_FALSE]; TerminalIO.PutRope ["MintSchematics\n"]; CDProperties.PutDesignProp [comm.design, $MintCmdDir]; ExtractAndMint[Sisyph.mode, comm]; TerminalIO.PutRope ["Mint finished.\n"]; }; clkName: Rope.ROPE _ "public.CK"; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Layout->Mint", doc: "Fast Timing Simulation", key: $MintLayoutSel, proc: MintFromLayout]; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Schema->Mint", doc: "Fast Timing Simulation", key: $MintSchemSel, proc: MintFromSchematics]; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Layout->Check", doc: "Electrical Static Check", key: $CheckLayoutSel, proc: CheckFromLayout]; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Schema->Check", doc: "Electrical Static Check", key: $CheckSchemSel, proc: CheckFromSchematics]; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Layout->Timing", doc: "Critical time path evaluation", key: $TimingLayoutSel, proc: TimingFromLayout]; CDCommandOps.RegisterWithMenu [menu: $ProgramMenu, entry: "Schema->Timing", doc: "Critical time path evaluation", key: $TimingSchemSel, proc: TimingFromSchematics]; TerminalIO.PutRope ["CDMint package loaded.\n"]; END.