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;
~
BEGIN
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 ~ {
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;
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 ~ {
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;
};
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,
$MintRatios => RemoteRatios,
$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"];
};
RemoteRatios: CedarProcess.ForkableProc ~ {
forkData: ForkData = NARROW[data];
circuit: Mint.Circuit = forkData.circuit ;
mode: Sinix.Mode = forkData.mode;
PrepareCircuit[circuit, mode#Sisyph.mode];
Mint.CheckRatios[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];
don't Mint.KillCircuit[circuit] because it will destroy the plot content
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: $MintRatios, proc: ExtractAndForkMint, queue: doQueue, setWDir: TRUE];
CDSequencerExtras.RegisterCommand[key: $MintTiming, proc: ExtractAndForkMint, queue: doQueue, setWDir: TRUE];