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;
~
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 ~ {
PROC [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE];
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 ~ {
PROC [parent: REF ANY, clientData: REF ANY ← NIL, mouseButton: MouseButton ← red, shift, control: BOOL ← FALSE]
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] ~ {
Called by ChipNDale upon activation of the 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] ~ {
Called by ChipNDale upon activation of the 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] ~ {
Called by ChipNDale upon activation of the 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] ~ {
Called by ChipNDale upon activation of the 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] ~ {
Called by ChipNDale upon activation of the 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] ~ {
Called by ChipNDale upon activation of the 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"];