MintInputImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Christian LeCocq April 18, 1987 10:25:17 am PDT
Bertrand Serlet October 18, 1986 8:12:25 pm PDT
DIRECTORY
Core,
CoreClasses,
CoreFlat,
CoreOps,
CoreProperties,
ElectricalCoreClasses,
HashTable,
IO,
Mint,
PWCore,
Rope,
Schedule,
WriteCapa;
MintInputImpl: CEDAR PROGRAM
IMPORTS
CoreClasses,
CoreFlat,
CoreOps,
CoreProperties,
ElectricalCoreClasses,
HashTable,
IO,
Mint,
PWCore,
Schedule,
WriteCapa
EXPORTS
Mint
~ BEGIN OPEN Mint;
FlatCellProc: TYPE = PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec ← CoreFlat.allFlatCells, flatCell: CoreFlat.FlatCellTypeRec ← [], instance: CoreClasses.CellInstance ← NIL, parent: Core.CellType ← NIL, flatParent: CoreFlat.FlatCellTypeRec ← [], circuit: Circuit, wireName: HashTable.Table, ignoreFlag, capaEvalFlag: BOOLEAN];
some usefull definitions
defaultIndex: NATLAST[NAT];
kilo: REAL = 1000.0;
TypeTable: PUBLIC ARRAY CoreClasses.TransistorType OF TType ←
[NEW[TTypeRec ← ["nETran", 0.0012, 0.00025, 20000.0]],
NEW[TTypeRec ← ["pETran", 0.0012, 0.00025, 50000.0]],
NEW[TTypeRec ← ["nDTran", 0.0012, 0.00025, 20000.0]]];
debug: BOOLFALSE;
verbose: BOOLFALSE;
debugCellType: Core.CellType ← NIL;
debugCircuit: Circuit ← NIL;
debugNode: Node ← NIL;
debugNodeList: NodeList ← NIL;
ignoreMe: PUBLIC ATOM ← CoreProperties.RegisterProperty[
prop: $MintIgnoreMe,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
];
Basic data stuctures builders
CreateCircuit: PUBLIC PROC [rootCell: Core.CellType] RETURNS [circuit: Circuit] ~ {
WireToNode: PROC[wire: Core.Wire] = {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [
flatCell: CoreFlat.rootCellType,
wireRoot: public,
wire: wire
]];
node: Node ← BuildNode[flatWire, circuit];
}; -- GuessInput
circuit ← NEW[CircuitRec];
circuit.rootCell ← rootCell;
circuit.info ← NEW[InfoRec];
circuit.nodeTable ← HashTable.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash];
CreatePrivate[circuit];
CoreOps.VisitRootAtomics[root: rootCell.public, eachWire: WireToNode];
};
BuildNode: PUBLIC PROC[flatWire: CoreFlat.FlatWire, circuit: Circuit] RETURNS [Node] = {
This procedure sees if a given node exists, and makes a new one if necessary. A pointer is returned to the new or existing node.
new: Node;
val: HashTable.Value;
found: BOOLEAN;
[found: found, value: val] ← HashTable.Fetch[circuit.nodeTable, flatWire];
IF found THEN RETURN[NARROW[val]];
new ← NEW[NodeRec];
new.flatWire ← flatWire;
IF debug THEN new.watched ← TRUE; -- keeps everything for ever if you debug the cell ... or the program.
[] ← HashTable.Store[table: circuit.nodeTable, key: flatWire, value: new];
circuit.info.totalNodes ← circuit.info.totalNodes + 1;
new.cap ← WriteCapa.GetRootCap[flatWire.wire];
new.ignoreMe ← CheckIgnoreProp[flatWire.wire];
new.fetSeq ← NEW[FetSeqRec[2]];
RETURN [new];
};
CheckIgnoreProp: PROC [wire: Core.Wire] RETURNS [ignored: BOOLEAN] ~ {
ignored ← NARROW[CoreProperties.GetWireProp[from: wire, prop: ignoreMe], ATOM]=$TRUE;
};
AddFetToNode: PROC [fet: Fet, node: Node, circuit: Circuit] ~ {
fetSeq: FetSeq;
nTotal: NAT ← node.fetSeq.size;
nUsed: NAT ← node.fetSeq.nUsed;
IF nUsed<nTotal THEN {
node.fetSeq.elements[nUsed] ← fet;
node.fetSeq.nUsed ← nUsed+1;
RETURN
};
ooops! sounds like we've exceded our available space...
IF nFets>127 THEN fetSeq ← NEW[FetSeqRec[nFets+1]]
ELSE {
poolIndex: NAT ←
IF circuit.private.fetSeqPool[nFets+1]=NIL THEN fetSeq ← NEW[FetSeqRec[nFets+1]]
ELSE {
fetSeq ← circuit.private.fetSeqPool[nFets+1].first;
circuit.private.fetSeqPool[nFets+1] ← circuit.private.fetSeqPool[nFets+1].rest;
};
IF nFets>0 THEN circuit.private.fetSeqPool[nFets] ← CONS[node.fetSeq, circuit.private.fetSeqPool[nFets]];
};
IF fetSeq.size#nFets+1 THEN ERROR; --temporary while debug (hopefully..)
fetSeq ← NEW[FetSeqRec[2*nTotal]];
FOR i: NAT IN [0..nUsed) DO
fetSeq.elements[i] ← node.fetSeq.elements[i];
ENDLOOP;
fetSeq.elements[nUsed] ← fet;
node.fetSeq ← fetSeq;
node.fetSeq.nUsed ← nUsed+1;
};
GetFetType: PROC [l, w: NAT, type: CoreClasses.TransistorType, circuit: Circuit] RETURNS [fType: FetType] ~ {
FOR fTList: LIST OF FetType ← circuit.fetTypeList, fTList.rest UNTIL fTList=NIL DO
IF fTList.first.l#l THEN LOOP;
IF fTList.first.w#w THEN LOOP;
IF fTList.first.type#type THEN LOOP;
RETURN[fTList.first];
ENDLOOP;
fType ← NEW[FetTypeRec ← [l, w, type, w/(l * TypeTable[type].rOn)]];
circuit.fetTypeList ← CONS[fType, circuit.fetTypeList];
};
BuildFet: PROC[gate, ch1, ch2: CoreFlat.FlatWire, type: CoreClasses.TransistorType, l, w: NAT, circuit: Circuit] = {
This procedure builds a transistor data structure and links it into the network under construction.
cap: REAL;
fet: Fet;
fet ← NEW[FetRec];
fet.gate ← BuildNode[gate, circuit];
fet.gate.cap ← fet.gate.cap+TypeTable[type].cPerArea*l*w;
fet.ch1 ← BuildNode[ch1, circuit];
fet.ch1.cap ← fet.ch1.cap+TypeTable[type].cPerWidth*w;
fet.ch2 ← BuildNode[ch2, circuit];
fet.ch2.cap ← fet.ch2.cap+TypeTable[type].cPerWidth*w;
fet.switch ← FALSE;
AddFetToNode[fet, fet.gate, circuit];
fet.type ← GetFetType[l, w, type, circuit];
IF ~fet.ch1.fixedV THEN
IF fet.ch1 # fet.gate THEN AddFetToNode[fet, fet.ch1, circuit];
IF ~fet.ch2.fixedV THEN
IF (fet.ch2 # fet.gate) AND (fet.ch2 # fet.ch1) THEN AddFetToNode[fet, fet.ch2, circuit];
circuit.info.totalFets[fet.type.type] ← circuit.info.totalFets[fet.type.type] + 1;
};
Input From Core
NextCellType: PROC [cell: Core.CellType, target: CoreFlat.FlatCellTypeRec, flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, parent: Core.CellType, flatParent: CoreFlat.FlatCellTypeRec, circuit: Circuit, wireName: HashTable.Table, ignoreFlag, capaEvalFlag: BOOLEAN, proc: FlatCellProc] = {
BindCellType: CoreFlat.UnboundFlatCellProc = {
BindPublicToActual: CoreOps.EachWirePairProc = {
PROC [actualWire, publicWire: Wire]
IF publicWire.size=0 THEN {
flatWire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[table: wireName, key: actualWire].value];
[] ← HashTable.Store[table: wireName, key: publicWire, value: flatWire];
IF CheckIgnoreProp[publicWire] THEN {
node: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, flatWire].value];
node.ignoreMe ← TRUE;
};
};
};
IF CoreOps.VisitBinding[actual: IF instance=NIL OR instance.type#cell THEN previous.public ELSE instance.actual, public: cell.public, eachWirePair: BindPublicToActual] THEN ERROR;
proc[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag];
};
previous: Core.CellType ← cell;
CoreFlat.NextUnboundCellType[cell, target, flatCell, instance, defaultIndex, parent, flatParent, circuit, BindCellType];
};
Flatten: FlatCellProc = {
cellIgnoreMe: ATOMNARROW[CoreProperties.GetCellTypeProp[cell, ignoreMe]];
instanceIgnoreMe: ATOMIF instance#NIL THEN NARROW[CoreProperties.GetCellInstanceProp[instance, ignoreMe]] ELSE NIL;
layoutAtom: ATOM ← PWCore.GetLayoutAtom[cell];
IF cellIgnoreMe#NIL THEN ignoreFlag ← cellIgnoreMe=$TRUE;
IF instanceIgnoreMe#NIL THEN ignoreFlag ← instanceIgnoreMe=$TRUE;
IF layoutAtom=$Get OR layoutAtom=$GetAndFlatten THEN capaEvalFlag ← FALSE;
SELECT cell.class FROM
ElectricalCoreClasses.capacitorCellClass => {
gndNode: Node ← Mint.NodeFromRope["public.Gnd", circuit];
n0Wire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[wireName, cell.public[0]].value];
n0Node: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, n0Wire].value];
n1Wire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[wireName, cell.public[1]].value];
n1Node: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, n1Wire].value];
capa: ElectricalCoreClasses.Capacitor ← NARROW[cell.data];
SELECT TRUE FROM
n0Node=gndNode => n1Node.cap ← n1Node.cap+capa.value;
n1Node=gndNode => n0Node.cap ← n0Node.cap+capa.value;
ENDCASE => IO.PutF[StdOut, "Capacitor between %g and %g discarded\n", IO.rope[Mint.RopeFromNode[n0Node, circuit]], IO.rope[Mint.RopeFromNode[n0Node, circuit]]];
};
ElectricalCoreClasses.signalGeneratorCellClass => {
nWire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[wireName, cell.public[0]].value];
nNode: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, nWire].value];
sig: ElectricalCoreClasses.SignalGenerator ← NARROW[cell.data];
nNode.input ← TRUE;
SELECT sig.type FROM
DC => nNode.history ← Schedule.CreateHistory[0.0, sig.onLevel*kilo];
RectWave => {
delay: ps ← sig.tDelay*kilo;
offLevel: mVolt ← sig.offLevel*kilo;
onLevel: mVolt ← sig.onLevel*kilo;
tRise: ps ← sig.tRise*kilo;
tFall: ps ← sig.tFall*kilo;
width: ps ← sig.width*kilo;
period: ps ← sig.period*kilo;
nNode.history ← Schedule.CreateHistory[0.0, offLevel];
THROUGH [0..3] DO
nNode.history ← Schedule.AddToHistory[nNode.history, delay, offLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+tRise, onLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+width-tFall, onLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+width, offLevel];
delay ← delay+period;
ENDLOOP;
};
OneShot => {
delay: ps ← sig.tDelay*kilo;
offLevel: mVolt ← sig.offLevel*kilo;
onLevel: mVolt ← sig.onLevel*kilo;
tRise: ps ← sig.tRise*kilo;
tFall: ps ← sig.tFall*kilo;
width: ps ← sig.width*kilo;
nNode.history ← Schedule.CreateHistory[0.0, offLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay, offLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+tRise, onLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+width-tFall, onLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+width, offLevel];
};
Step => {
delay: ps ← sig.tDelay*kilo;
offLevel: mVolt ← sig.offLevel*kilo;
onLevel: mVolt ← sig.onLevel*kilo;
tRise: ps ← sig.tRise*kilo;
nNode.history ← Schedule.CreateHistory[0.0, offLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay, offLevel];
nNode.history ← Schedule.AddToHistory[nNode.history, delay+tRise, onLevel];
};
ENDCASE => ERROR;
};
ElectricalCoreClasses.probeCellClass => {
IF NARROW[cell.data, ElectricalCoreClasses.Probe].type=Voltage THEN {
nWire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[wireName, cell.public[0]].value];
nNode: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, nWire].value];
nNode.watched ← TRUE;
}
ELSE IO.PutF[StdOut, "No current probes allowed\n"];
};
ElectricalCoreClasses.panelCellClass => {
panel: ElectricalCoreClasses.Panel ← NARROW[cell.data];
circuit.info.tStart ← panel.tMin;
circuit.info.tStop ← panel.tMax;
};
CoreClasses.transistorCellClass => {
gateWire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.gate]]].value];
ch1Wire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch1]]].value];
ch2Wire: CoreFlat.FlatWire ← NARROW[HashTable.Fetch[table: wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch2]]].value];
tran: CoreClasses.Transistor ← NARROW[cell.data];
BuildFet[gateWire, ch1Wire, ch2Wire, tran.type, tran.length, tran.width, circuit];
};
CoreClasses.recordCellClass => {
rct: CoreClasses.RecordCellType ← NARROW[cell.data];
InsertNonPublicWires[cell.public, rct.internal, flatCell, circuit, wireName, ignoreFlag, capaEvalFlag];
NextCellType[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag, Flatten]
};
ENDCASE => {
IF cell.class.recast=NIL THEN IO.PutF[StdOut, "What is a %g ?\n", IO.rope[cell.class.name]]
ELSE NextCellType[cell, target, flatCell, instance, parent, flatParent, circuit, wireName, ignoreFlag, capaEvalFlag, Flatten]
};
};
InsertNonPublicWires: PROC [public, internal: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, circuit: Circuit, wireName: HashTable.Table, ignoreFlag, capaEvalFlag: BOOLEAN] ~ {
MarkAtomicPublic: PROC[wire: Core.Wire] = {
[] ← HashTable.Store[table: publicsTable, key: wire, value: $Public];
};
InsertInternal: PROC[wire: Core.Wire] = {
IF NOT HashTable.Fetch[table: publicsTable, key: wire].found THEN {
node: Node ← InsertWire[wire, flatCell, circuit, wireName];
node.ignoreMe ← ignoreFlag;
IF capaEvalFlag THEN node.cap ← node.cap+circuit.info.eachWireCapa;
};
};
publicsTable: HashTable.Table ← HashTable.Create[public.size+1];
CoreOps.VisitRootAtomics[root: public, eachWire: MarkAtomicPublic];
CoreOps.VisitRootAtomics[root: internal, eachWire: InsertInternal];
};
InsertWire: PROC [wire: Core.Wire, flatCell: CoreFlat.FlatCellTypeRec, circuit: Circuit, wireName: HashTable.Table, wireRoot: CoreFlat.WireRoot ← internal] RETURNS[node: Node]= {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec];
flatWire.flatCell ← flatCell;
flatWire.wireRoot ← wireRoot;
flatWire.wire ← wire;
node ← BuildNode[flatWire, circuit];
[] ← HashTable.Store[table: wireName, key: wire, value: flatWire];
};
NetFromCore: PUBLIC PROC[circuit: Circuit, layout: BOOLEANTRUE] = {
InsertPublic: PROC[wire: Core.Wire] = {
[] ← InsertWire[wire, CoreFlat.rootCellType, circuit, wireName, public];
};
wireName: HashTable.Table ← HashTable.Create[];
IO.PutF[Mint.StdOut, "\nConverting cell %g . . .", IO.rope[CoreOps.GetCellTypeName[circuit.rootCell]]];
CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: InsertPublic];
Flatten[cell: circuit.rootCell, circuit: circuit, wireName: wireName, ignoreFlag: FALSE, capaEvalFlag: ~layout];
IO.PutRope[Mint.StdOut, "Finished\n"];
};
Circuit Preparation
Stats: PUBLIC PROC[circuit: Circuit] = {
total: INT ← 0;
IO.PutF[Mint.StdOut, "Total number of nodes: %d.\n", IO.int[circuit.info.totalNodes]];
FOR i: CoreClasses.TransistorType IN CoreClasses.TransistorType DO
IF circuit.info.totalFets[i] = 0 THEN LOOP;
IO.PutF[Mint.StdOut, "Number of %s transistors: %d.\n", IO.rope[TypeTable[i].name], IO.int[circuit.info.totalFets[i]]];
total ← total + circuit.info.totalFets[i];
ENDLOOP;
IO.PutF[Mint.StdOut, "Total number of transistors: %d.\n", IO.int[total]];
};
InputData: PUBLIC PROC [circuit: Circuit, fixedVList: NodeList, layout: BOOLEANTRUE, eachWireCapa: pF 𡤀.0] ~ {
GuessInput: PROC[wire: Core.Wire] = {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [
flatCell: CoreFlat.rootCellType,
wireRoot: public,
wire: wire
]];
node: Node ← NARROW[HashTable.Fetch[circuit.nodeTable, flatWire].value];
IF ~node.fixedV THEN {
node.input ← TRUE;
FOR i: NAT IN [0..node.fetSeq.nUsed) DO
fet: Fet ← node.fetSeq[i];
IF fet.ch1=node OR fet.ch2=node THEN {
node.input ← FALSE;
EXIT;
};
ENDLOOP;
};
node.watched ← TRUE;
}; -- GuessInput
circuit.info.eachWireCapa ← eachWireCapa;
FOR iNodeList: NodeList ← fixedVList, iNodeList.rest UNTIL iNodeList = NIL DO
iNodeList.first.fixedV ← TRUE;
ENDLOOP;
NetFromCore[circuit, layout];
CoreOps.VisitRootAtomics[root: circuit.rootCell.public, eachWire: GuessInput];
Stats[circuit];
PrepareSets[circuit, fixedVList];
};
NextNodeList: PROC [set: Set, fetList: FetList] RETURNS [nodeList: NodeList ← NIL] ~ {
FOR iFetList: FetList ← fetList, iFetList.rest UNTIL iFetList = NIL DO
IF NOT iFetList.first.ch1.done THEN {
nodeList ← CONS[iFetList.first.ch1, nodeList];
iFetList.first.ch1.done ← TRUE;
AddNodeToSet[set, iFetList.first.ch1];
};
IF NOT iFetList.first.ch2.done THEN {
nodeList ← CONS[iFetList.first.ch2, nodeList];
iFetList.first.ch2.done ← TRUE;
AddNodeToSet[set, iFetList.first.ch2];
};
ENDLOOP;
}; --NextNodeList
NextFetList: PROC [set: Set, nodeList: NodeList] RETURNS [fetList: FetList ← NIL] ~ {
FOR iNodeList: NodeList ← nodeList, iNodeList.rest UNTIL iNodeList = NIL DO
FOR i: NAT IN [0..iNodeList.first.fetSeq.nUsed) DO
fet: Fet = iNodeList.first.fetSeq[i];
IF NOT fet.done THEN
IF fet.gate # iNodeList.first THEN {
fetList ← CONS[fet, fetList];
fet.done ← TRUE;
AddFetToSet[set, fet];
};
ENDLOOP;
ENDLOOP;
}; --NextFetList
AddNodeToSet: PROC [set: Set, node: Node] ~ {
set.lNodes ← CONS[node, set.lNodes];
set.type.nNodes ← set.type.nNodes+1;
node.done ← TRUE;
};
AddFetToSet: PROC [set: Set, fet: Fet] ~ {
set.lFets ← CONS[fet, set.lFets];
fet.done ← TRUE;
set.type.nFets[fet.type.type] ← set.type.nFets[fet.type.type]+1;
};
PrepareSets: PUBLIC PROC [circuit: Circuit, fixedVList: NodeList] ~ {
FindOneSet: HashTable.EachPairAction ~ {
PROC [key: Key, value: Value] RETURNS [quit: BOOLEANFALSE];
nodeList: NodeList;
fetList: FetList;
set: Set;
node: Node ← NARROW[value];
IF node.done THEN RETURN;
set ← NEW[SetRec];
set.type ← NEW[SetTypeRec];
nodeList ← LIST[node];
AddNodeToSet[set, node];
UNTIL nodeList = NIL DO
fetList ← NextFetList[set, nodeList];
nodeList ← NextNodeList[set, fetList];
ENDLOOP;
FindInputs[set];
FindFixedV[set, fixedVList, GndNode, VddNode];
FOR il: Library ← circuit.library, il.rest UNTIL il=NIL DO
IF TypeEqual[set.type, il.first.type] THEN {
il.first.nElem ← il.first.nElem+1;
il.first.setList ← CONS[set, il.first.setList];
set.type ← il.first.type;
RETURN;
};
ENDLOOP;
circuit.library ← CONS[NEW[LibraryElemRec ← [set.type, 1, LIST[set]]], circuit.library];
};
GndNode: Node ← Mint.NodeFromRope["public.Gnd", circuit];
VddNode: Node ← Mint.NodeFromRope["public.Vdd", circuit];
FOR inode: NodeList ← fixedVList, inode.rest UNTIL inode=NIL DO
inode.first.done ← TRUE;
inode.first.input ← TRUE;
ENDLOOP;
[] ← HashTable.Pairs[circuit.nodeTable, FindOneSet]
}; -- PrepareSets
FindInputs: PROC [set: Set] ~ {
found: BOOLEAN;
FOR ifet: FetList ← set.lFets, ifet.rest UNTIL ifet=NIL DO
found ← FALSE;
FOR inode: NodeList ← set.lNodes, inode.rest UNTIL inode=NIL DO
IF inode.first=ifet.first.gate THEN {
found ← TRUE;
EXIT;
};
ENDLOOP;
IF ~found THEN {
found ← FALSE;
FOR inode: NodeList ← set.inList, inode.rest UNTIL inode=NIL DO
IF inode.first=ifet.first.gate THEN {
found ← TRUE;
EXIT;
};
ENDLOOP;
IF ~found THEN {
set.type.nInput ← set.type.nInput+1;
set.inList ← CONS[ifet.first.gate, set.inList];
ifet.first.gate.setList ← CONS[set, ifet.first.gate.setList]
};
};
ENDLOOP;
};
FindFixedV: PROC [set: Set, fixedVList: NodeList, GndNode, VddNode: Node] ~ {
found: BOOLEAN;
FOR ifet: FetList ← set.lFets, ifet.rest UNTIL ifet=NIL DO
FOR fix: NodeList ← fixedVList, fix.rest UNTIL fix=NIL DO
IF ifet.first.ch1=fix.first OR ifet.first.ch2=fix.first THEN {
IF fix.first=VddNode THEN set.type.nVddTran ← set.type.nVddTran+1;
IF fix.first=GndNode THEN set.type.nGndTran ← set.type.nGndTran+1;
found ← FALSE;
FOR inode: NodeList ← set.fixedV, inode.rest UNTIL inode=NIL DO
IF inode.first=fix.first THEN {
found ← TRUE;
EXIT;
};
ENDLOOP;
IF ~found THEN set.fixedV ← CONS[fix.first, set.fixedV];
};
ENDLOOP;
ENDLOOP;
};
TypeEqual: PROC [s1, s2: SetType] RETURNS [ok: BOOLEANFALSE] ~ {
FOR tt: CoreClasses.TransistorType IN CoreClasses.TransistorType DO
IF s1.nFets[tt]#s2.nFets[tt] THEN RETURN;
ENDLOOP;
IF s1.nVddTran#s2.nVddTran THEN RETURN;
IF s1.nGndTran#s2.nGndTran THEN RETURN;
IF s1.nNodes#s2.nNodes THEN RETURN;
IF s1.nInput#s2.nInput THEN RETURN;
ok ← TRUE;
};
PrintSetType: PROC [out: IO.STREAM, setType: SetType] ~ {
IO.PutF[out, " %4d, %4d,", IO.int[setType.nFets[nE]], IO.int[setType.nFets[pE]]];
IO.PutF[out, " %4d, %4d, %4d, %4d", IO.int[setType.nVddTran], IO.int[setType.nGndTran], IO.int[setType.nNodes], IO.int[setType.nInput]];
};
SolveInverter: PROC [set: Set, t: ps] RETURNS [tlast: ps] ~ {
out: Node ~ set.lNodes.first;
in: Node ~ set.inList.first;
... to be finished.
};
ErrMsg: PROC [nodeList: NodeList, msg: Rope.ROPE, circuit: Circuit] ~ {
IO.PutF[Mint.StdOut, "\n%g:", IO.rope[msg]];
FOR iNodeList: NodeList ← nodeList, iNodeList.rest UNTIL iNodeList=NIL DO
IO.PutF[Mint.StdOut, "\n%g", IO.rope[Mint.RopeFromNode[iNodeList.first, circuit]]];
ENDLOOP;
IO.PutF[Mint.StdOut, "\n" ];
};
CheckLibrary: PUBLIC PROC [circuit: Circuit] ~ {
n: NAT ← 0;
FOR il: Library ← circuit.library, il.rest UNTIL il=NIL DO
SELECT TRUE FROM
il.first.type.nFets[nE]+il.first.type.nFets[pE]=0 => FOR iSetList: SetList ← il.first.setList, iSetList.rest UNTIL iSetList=NIL DO
IF iSetList.first.lNodes.first.flatWire.wireRoot#public THEN {
IF iSetList.first.lNodes.first.setList=NIL THEN ErrMsg[iSetList.first.lNodes, "This Node is isolated", circuit] ELSE ErrMsg[iSetList.first.lNodes, "This Node is not loaded by any fet", circuit]};
ENDLOOP;
il.first.type.nVddTran=0 => FOR iSetList: SetList ← il.first.setList, iSetList.rest UNTIL iSetList=NIL DO
ErrMsg[iSetList.first.lNodes, "These Nodes have no path to Vdd", circuit];
ENDLOOP;
il.first.type.nGndTran=0 => FOR iSetList: SetList ← il.first.setList, iSetList.rest UNTIL iSetList=NIL DO
ErrMsg[iSetList.first.lNodes, "These Nodes have no path to Gnd", circuit];
ENDLOOP;
ENDCASE;
ENDLOOP;
};
OutputResults: PUBLIC PROC [circuit: Circuit] ~ {
n: NAT ← 0;
IO.PutF[Mint.StdOut, " nE pE ^Vdd ^Gnd nodes inputs\n"];
FOR il: Library ← circuit.library, il.rest UNTIL il=NIL DO
IO.PutF[Mint.StdOut, "%5d el: %5d Type: ", IO.int[n], IO.int[il.first.nElem]];
PrintSetType[Mint.StdOut, il.first.type];
IO.PutF[Mint.StdOut, "\n" ];
n ← n+1;
ENDLOOP;
};
END.