<> <> <> <> <> <<>> <> DIRECTORY Buttons USING [Create, ReLabel, ButtonProc, Button, SetDisplayStyle], CedarProcess USING [Fork, ForkableProc], Containers USING [Container, Create], CD USING [ Design, Instance], CDOps USING [SelectedInstance], CDSequencer USING [Command], CDSequencerExtras USING [RegisterCommand], Core USING [CellType, Wire], CoreCDUser USING [EnumerateSelectedCellTypes, EachRootCellTypeProc], CoreFlat USING [FlatWire, FlatWireRec, rootCellType, PathError], CoreOps USING [GetCellTypeName, VisitRootAtomics], ExtractOps USING [IsSchematic, GetExtractMode], Icons USING [NewIconFromFile], ImagerFont USING [Font, Find], IO USING [real], Menus USING [MenuProc, CreateEntry, AppendMenuEntry, CreateMenu, Menu], Mint, RefTab USING [Fetch, Ref], Rope USING [ROPE, Cat, Replace], Sisyph USING [mode], Sinix USING [Mode], SinixOps, TerminalIO USING [PutRope, PutRopes, PutF, TOS], ViewerOps USING [DestroyViewer, OpenIcon], WriteCapa; MintCmds: CEDAR MONITOR IMPORTS Buttons, CedarProcess, Containers, CoreFlat, CDOps, CDSequencerExtras, CoreOps, CoreCDUser, ExtractOps, Icons, IO, RefTab, ImagerFont, Menus, Mint, Rope, Sisyph, SinixOps, TerminalIO, ViewerOps, WriteCapa ~ BEGIN MintAction: TYPE = {simulate, check, findPaths}; ForkData: TYPE = REF ForkDataRec; ForkDataRec: TYPE = RECORD [ circuit: Mint.Circuit, design: CD.Design, instance: CD.Instance, mode: Sinix.Mode ]; Key: TYPE = REF KeyRec; KeyRec: TYPE = RECORD [ locked: BOOL _ TRUE, unlocked: CONDITION ]; debugCircuit: Mint.Circuit _ NIL; verbose: BOOLEAN _ FALSE; maxNumber: NAT _ 10; nOfPaths: CARD _ 5; nNodes: CARD _ 16; buttonFont: ImagerFont.Font _ ImagerFont.Find["Xerox/TiogaFonts/Gacha10"]; defaultCapa: REAL _ 0.5; defaultPublicCapa: REAL _ 0.5; vdd: REAL _ 5000.0; vTn: REAL _ 780.0; vbb: REAL _ 1200.0; --mV clkName: Rope.ROPE _ "public.CK"; 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; node.exactValue _ FALSE; 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[RefTab.Fetch[circuit.nodeTable, flatWire].val]; 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.exactValue 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[RefTab.Fetch[circuit.nodeTable, flatWire].val]; IF node.exactValue 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/DATools7.0/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; }; 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; }; ExtractAndForkMint: PROC [comm: CDSequencer.Command] ~ { Doit: CoreCDUser.EachRootCellTypeProc ~ { <<[root: Core.CellType] RETURNS [quit: BOOL _ FALSE]>> name: Rope.ROPE _ CoreOps.GetCellTypeName[root]; forkData: ForkData _ NEW[ForkDataRec _ [ design: comm.design, mode: ]]; isLayout: BOOLEAN; multiple: BOOLEAN; TerminalIO.PutRopes ["Mint on ", name, " ... "]; [forkData.instance, multiple] _ CDOps.SelectedInstance[comm.design]; isLayout _ NOT ExtractOps.IsSchematic[comm.design, forkData.instance.ob]; forkData.mode _ ExtractOps.GetExtractMode[comm.design, forkData.instance.ob]; IF isLayout THEN WriteCapa.WriteWireCapa[root, comm.design.technology.key]; forkData.circuit _ Mint.CreateCircuit[root, isLayout, defaultPublicCapa]; [] _ CedarProcess.Fork[ action: SELECT comm.key FROM $MintSimulate => RemoteSimulate, $MintCheck => RemoteCheck, $MintTiming => RemoteTiming, ENDCASE => ERROR, data: forkData, options: [priority: background, usePriority: TRUE] ]; TerminalIO.PutRope [" Mint forked.\n"]; }; [] _ CoreCDUser.EnumerateSelectedCellTypes[comm.design, Doit]; }; PrepareCircuit: PROC [circuit: Mint.Circuit, isLayout: BOOLEAN] ~ { gndNode, vddNode, vbbNode: Mint.Node; fixedV: Mint.NodeList; isVbb: BOOL _ TRUE; 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/1000.0]]; Mint.EditNodeHistory[vbbNode, 0.0, vbb]; fixedV _ LIST[gndNode, vddNode, vbbNode]; } ELSE { fixedV _ LIST[gndNode, vddNode]; }; Mint.InputData[circuit, fixedV, isLayout, defaultCapa]; IF isVbb THEN [] _ BiasFets[vbbNode]; IF verbose THEN Mint.OutputResults[circuit]; }; BuildList: PROC [lastNode: Mint.Node] RETURNS[flatWires: LIST OF SinixOps.FlatWireRec]~ { flatWires _ LIST[lastNode.flatWire^]; IF Mint.GetNode[lastNode] THEN { lastNode _ lastNode.prevNodeU; IF lastNode=NIL THEN RETURN; flatWires _ CONS[lastNode.flatWire^, flatWires]; }; DO lastNode _ lastNode.prevNodeD; IF lastNode=NIL THEN RETURN; flatWires _ CONS[lastNode.flatWire^, flatWires]; lastNode _ lastNode.prevNodeU; IF lastNode=NIL THEN RETURN; flatWires _ CONS[lastNode.flatWire^, flatWires]; ENDLOOP; }; ShowPath: PROC [decoration: SinixOps.Decoration, design: CD.Design, instance: CD.Instance, root: Core.CellType, lastNode: Mint.Node] ~ { flatWires: LIST OF SinixOps.FlatWireRec _ BuildList[lastNode]; SinixOps.HighlightNets[decoration, design, instance, root, flatWires]; }; RemoteTiming: CedarProcess.ForkableProc ~ { forkData: ForkData = NARROW[data]; worst: Mint.ps; circuit: Mint.Circuit = forkData.circuit; design: CD.Design = forkData.design; instance: CD.Instance = forkData.instance; mode: Sinix.Mode = forkData.mode; clkList: Mint.NodeList; lastNodes: Mint.PathArray; warningMsg: Rope.ROPE _ NIL; PrepareCircuit[circuit, mode#Sisyph.mode]; clkList _ LIST[ Mint.NodeFromRope[clkName, circuit ! CoreFlat.PathError => {warningMsg _ Rope.Cat["warning: no ", clkName, " wire"]; CONTINUE}]]; IF warningMsg#NIL THEN clkList _ MakeMintPanelViewer[circuit]; worst _ Mint.RecordPaths[circuit, clkList]; TerminalIO.PutF["longest time: %4.1fns\n", IO.real[worst/1000.0]]; [worst, lastNodes] _ Mint.FindSlowestPaths[circuit, nOfPaths, TRUE]; Mint.PrintPathArray[lastNodes, circuit]; ShowPath[mode.decoration, design, instance, circuit.rootCell, lastNodes[lastNodes.size-1].node]; Mint.KillCircuit[circuit]; }; RemoteCheck: CedarProcess.ForkableProc ~ { forkData: ForkData = NARROW[data]; circuit: Mint.Circuit = forkData.circuit ; mode: Sinix.Mode = forkData.mode; PrepareCircuit[circuit, mode#Sisyph.mode]; Mint.CheckLibrary[circuit]; Mint.KillCircuit[circuit]; TerminalIO.PutRope ["Check finished.\n"]; }; RemoteSimulate: CedarProcess.ForkableProc ~ { forkData: ForkData = NARROW[data]; circuit: Mint.Circuit = forkData.circuit ; mode: Sinix.Mode = forkData.mode; PrepareCircuit[circuit, mode#Sisyph.mode]; [] _ Mint.InteractiveSimulate[circuit]; <> TerminalIO.PutRope ["Simulation finished.\n"]; }; Mint.StdOut _ TerminalIO.TOS[]; TerminalIO.PutRope["Mint loaded\n"]; CDSequencerExtras.RegisterCommand[key: $MintSimulate, proc: ExtractAndForkMint, queue: doQueue, setWDir: TRUE]; CDSequencerExtras.RegisterCommand[key: $MintCheck, proc: ExtractAndForkMint, queue: doQueue, setWDir: TRUE]; CDSequencerExtras.RegisterCommand[key: $MintTiming, proc: ExtractAndForkMint, queue: doQueue, setWDir: TRUE]; END.