MintInputImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Bertrand Serlet October 18, 1986 8:12:25 pm PDT
Christian Le Cocq October 16, 1987 10:02:45 am PDT
DIRECTORY
Core,
CoreClasses,
CoreFlat,
CoreOps,
CoreProperties,
ElectricalCoreClasses,
IO,
Mint,
MintList,
MintPrivate,
PWCore,
RefTab,
Rope,
Schedule,
WriteCapa;
MintInputImpl: CEDAR PROGRAM
IMPORTS
CoreClasses,
CoreFlat,
CoreOps,
CoreProperties,
ElectricalCoreClasses,
IO,
Mint,
MintList,
MintPrivate,
PWCore,
RefTab,
Schedule,
WriteCapa
EXPORTS
Mint
~ BEGIN OPEN Mint, MintList;
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: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN];
some usefull definitions
defaultIndex: NATLAST[NAT];
kilo: REAL = 1000.0;
ignoreMe: PUBLIC ATOM ← CoreProperties.RegisterProperty[
prop: $MintIgnoreMe,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
];
discardMe: PUBLIC ATOM ← CoreProperties.RegisterProperty[
prop: $MintDiscardMe,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
];
oneWay: PUBLIC ATOM ← CoreProperties.RegisterProperty[
prop: $MintOneWay,
properties: CoreProperties.Props[[CoreProperties.propPrint, CoreProperties.PropDontPrint]]
];
TypeTable: PUBLIC ARRAY CoreClasses.TransistorType OF TType ←
[NEW[TTypeRec ← ["nE", 0.0012, 0.00025, 20000.0]],
NEW[TTypeRec ← ["pE", 0.0012, 0.00025, 50000.0]],
NEW[TTypeRec ← ["nD", 0.0012, 0.00025, 20000.0]]];
debug: BOOLFALSE;
verbose: BOOLFALSE;
debugCellType: Core.CellType ← NIL;
debugCircuit: Circuit ← NIL;
debugNode: Node ← NIL;
debugNodeList: NodeList ← NIL;
Basic data stuctures builders
CreateCircuit: PUBLIC PROC [rootCell: Core.CellType, layout: BOOLEANTRUE, eachPublicWireCapa: pF ← 0.0] RETURNS [circuit: Circuit] ~ {
WireToNode: PROC[wire: Core.Wire] = {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [
flatCell: CoreFlat.rootCellType,
wireRoot: public,
wire: wire
]];
node: Node ← CreateNode[flatWire, circuit, IF layout THEN WriteCapa.GetRootCap[flatWire.wire] ELSE eachPublicWireCapa];
};
circuit ← NEW[CircuitRec ← [
rootCell: rootCell,
info: NEW[MintPrivate.InfoRec],
nodeTable: RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash],
private: MintPrivate.CreatePrivate[]
]];
CoreOps.VisitRootAtomics[root: rootCell.public, eachWire: WireToNode];
};
CreateNode: PROC[flatWire: CoreFlat.FlatWire, circuit: Circuit, capa: pF] RETURNS [new: Node] = {
Creates a new node after checking that it has not been already inserted if the table.
val: RefTab.Val;
found: BOOLEAN;
[found: found, val: val] ← RefTab.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.
[] ← RefTab.Store[x: circuit.nodeTable, key: flatWire, val: new];
circuit.info.totalNodes ← circuit.info.totalNodes + 1;
new.cap ← capa;
new.ignoreMe ← CheckIgnoreProp[flatWire.wire];
new.fetSeq ← NEW[FetSeqRec[2]];
RETURN [new];
};
FetchNode: PROC[flatWire: CoreFlat.FlatWire, circuit: Circuit] RETURNS [node: Node] = {
Fetch an existing Node or fails
val: RefTab.Val;
found: BOOLEAN;
[found: found, val: val] ← RefTab.Fetch[circuit.nodeTable, flatWire];
IF found THEN RETURN[NARROW[val]]
ELSE ERROR; --deep internal bug
};
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, directional: BOOLEAN, circuit: Circuit] = {
This procedure builds a transistor data structure and links it into the network under construction.
cap: REAL;
fet: Fet;
fet ← NEW[FetRec ← [
gate: FetchNode[gate, circuit],
ch1: FetchNode[ch1, circuit],
ch2: FetchNode[ch2, circuit],
switch: FALSE,
directional: directional,
type: GetFetType[l, w, type, circuit]
]];
fet.gate.cap ← fet.gate.cap+TypeTable[type].cPerArea*l*w;
fet.ch1.cap ← fet.ch1.cap+TypeTable[type].cPerWidth*w;
fet.ch2.cap ← fet.ch2.cap+TypeTable[type].cPerWidth*w;
AddFetToNode[fet, fet.gate, 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: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN, proc: FlatCellProc] = {
BindCellType: CoreFlat.UnboundFlatCellProc = {
BindPublicToActual: CoreOps.EachWirePairProc = {
PROC [actualWire, publicWire: Wire]
IF publicWire.size=0 THEN {
flatWire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x: wireName, key: actualWire].val];
[] ← RefTab.Store[x: wireName, key: publicWire, val: flatWire];
IF CheckIgnoreProp[publicWire] THEN {
node: Node ← NARROW[RefTab.Fetch[circuit.nodeTable, flatWire].val];
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 = {
discardFlag: BOOLEANFALSE;
cellIgnoreMe: ATOMNARROW[CoreProperties.GetCellTypeProp[cell, ignoreMe]];
cellDiscardMe: ATOMNARROW[CoreProperties.GetCellTypeProp[cell, discardMe]];
instanceIgnoreMe: ATOMIF instance#NIL THEN NARROW[CoreProperties.GetCellInstanceProp[instance, ignoreMe]] ELSE NIL;
instanceDiscardMe: ATOMIF instance#NIL THEN NARROW[CoreProperties.GetCellInstanceProp[instance, discardMe]] ELSE NIL;
layoutAtom: ATOM ← PWCore.GetLayoutAtom[cell];
IF cellIgnoreMe#NIL THEN ignoreFlag ← cellIgnoreMe=$TRUE;
IF instanceIgnoreMe#NIL THEN ignoreFlag ← instanceIgnoreMe=$TRUE;
IF cellDiscardMe#NIL THEN discardFlag ← cellDiscardMe=$TRUE;
IF instanceDiscardMe#NIL THEN discardFlag ← instanceDiscardMe=$TRUE;
IF discardFlag THEN RETURN;
IF layoutAtom=$Get OR layoutAtom=$GetAndFlatten OR layoutAtom=$GetLibrary THEN capaEvalFlag ← FALSE;
SELECT cell.class FROM
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]
};
CoreClasses.transistorCellClass => {
directional: BOOLEAN ← CoreProperties.GetCellInstanceProp[instance, oneWay]#NIL OR CoreProperties.GetCellTypeProp[cell, oneWay]#NIL;
transistorLength: INTNARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.lengthProp], REF INT]^;
transistorWidth: INTNARROW[CoreProperties.GetCellTypeProp[cell, CoreClasses.widthProp], REF INT]^;
gateWire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.gate]]].val];
ch1Wire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch1]]].val];
ch2Wire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[x:wireName, key: cell.public[ORD[CoreClasses.TransistorPort.ch2]]].val];
tran: CoreClasses.Transistor ← NARROW[cell.data];
BuildFet[gateWire, ch1Wire, ch2Wire, tran.type, transistorLength, transistorWidth, directional, circuit];
};
ElectricalCoreClasses.capacitorCellClass => {
gndNode: Node ← Mint.NodeFromRope["public.Gnd", circuit];
n0Wire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[wireName, cell.public[0]].val];
n0Node: Node ← NARROW[RefTab.Fetch[circuit.nodeTable, n0Wire].val];
n1Wire: CoreFlat.FlatWire ← NARROW[RefTab.Fetch[wireName, cell.public[1]].val];
n1Node: Node ← NARROW[RefTab.Fetch[circuit.nodeTable, n1Wire].val];
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[RefTab.Fetch[wireName, cell.public[0]].val];
nNode: Node ← NARROW[RefTab.Fetch[circuit.nodeTable, nWire].val];
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[RefTab.Fetch[wireName, cell.public[0]].val];
nNode: Node ← NARROW[RefTab.Fetch[circuit.nodeTable, nWire].val];
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;
};
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: RefTab.Ref, ignoreFlag, capaEvalFlag: BOOLEAN] ~ {
MarkAtomicPublic: PROC[wire: Core.Wire] = {
[] ← RefTab.Store[x: publicsTable, key: wire, val: $Public];
};
InsertInternal: PROC[wire: Core.Wire] = {
IF NOT RefTab.Fetch[x: publicsTable, key: wire].found THEN {
node: Node ← InsertWire[wire, flatCell, circuit, wireName];
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [
flatCell: flatCell,
wireRoot: internal,
wire: wire
]];
node: Node ← CreateNode[flatWire, circuit, IF capaEvalFlag THEN circuit.info.eachWireCapa ELSE WriteCapa.GetRootCap[wire]];
[] ← RefTab.Store[x: wireName, key: wire, val: flatWire];
IF NOT node.ignoreMe THEN node.ignoreMe ← ignoreFlag;
};
};
publicsTable: RefTab.Ref ← RefTab.Create[public.size+1];
CoreOps.VisitRootAtomics[root: public, eachWire: MarkAtomicPublic];
CoreOps.VisitRootAtomics[root: internal, eachWire: InsertInternal];
};
NetFromCore: PROC[circuit: Circuit, layout: BOOLEANTRUE] ~ {
InsertPublic: PROC[wire: Core.Wire] = {
flatWire: CoreFlat.FlatWire ← NEW[CoreFlat.FlatWireRec ← [
flatCell: CoreFlat.rootCellType,
wireRoot: public,
wire: wire
]];
node: Node ← FetchNode[flatWire, circuit];
[] ← RefTab.Store[x: wireName, key: wire, val: node.flatWire];
};
wireName: RefTab.Ref ← RefTab.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"];
RefTab.Erase[wireName];
};
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[RefTab.Fetch[circuit.nodeTable, flatWire].val];
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 OR iFetList.first.ch1.tiedToDir THEN nodeList ← AddNode[set, iFetList.first.ch1, nodeList];
IF NOT iFetList.first.ch2.done OR iFetList.first.ch2.tiedToDir THEN nodeList ← AddNode[set, iFetList.first.ch2, nodeList];
ENDLOOP;
set.lNodes ← AppendNodeLists[set.lNodes, nodeList];
}; --NextNodeList
NextFetList: PROC [set: Set, nodeList: NodeList] RETURNS [fetList: FetList ← NIL] ~ {
FOR iNodeList: NodeList ← nodeList, iNodeList.rest UNTIL iNodeList = NIL DO
node: Node ← iNodeList.first;
FOR i: NAT IN [0..node.fetSeq.nUsed) DO
fet: Fet = node.fetSeq[i];
IF NOT fet.done THEN
SELECT node FROM
fet.gate  => NULL;
fet.ch1  => {
fetList ← CONS[fet, fetList];
fet.done ← TRUE;
set.type.nFets[fet.type.type] ← set.type.nFets[fet.type.type]+1;
};
fet.ch2  =>
IF NOT fet.directional THEN {
fetList ← CONS[fet, fetList];
fet.done ← TRUE;
set.type.nFets[fet.type.type] ← set.type.nFets[fet.type.type]+1;
}
ELSE node.tiedToDir ← TRUE;
ENDCASE => ERROR; --we don't care about fancy schematics
ENDLOOP;
ENDLOOP;
set.lFets ← AppendFetLists[set.lFets, fetList];
}; --NextFetList
AddNode: PROC [set: Set, node: Node, oldNodeList: NodeList] RETURNS [nodeList: NodeList] ~ {
nodeList ← CONS[node, oldNodeList];
node.set ← set;
set.type.nNodes ← set.type.nNodes+1;
node.done ← TRUE;
};
PrepareSets: PUBLIC PROC [circuit: Circuit, fixedVList: NodeList] ~ {
FindOneSet: RefTab.EachPairAction ~ {
PROC [key: Key, val: Val] RETURNS [quit: BOOLEANFALSE];
nodeList: NodeList;
set: Set;
node: Node ← NARROW[val];
IF node.done THEN RETURN;
set ← NEW[SetRec ← [type: NEW[SetTypeRec]]];
nodeList ← AddNode[set, node, NIL];
set.lNodes ← nodeList;
UNTIL nodeList = NIL DO
fetList: 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;
[] ← RefTab.Pairs[circuit.nodeTable, FindOneSet]
}; -- PrepareSets
FindInputs: PROC [set: Set] ~ {
set.selfInputs ← FALSE;
FOR ifet: FetList ← set.lFets, ifet.rest UNTIL ifet=NIL DO
thisNode: Node ← ifet.first.gate;
IF IsNodeInList[thisNode, set.lNodes] THEN set.selfInputs ← TRUE
ELSE IF NOT IsNodeInList[thisNode, set.inList] THEN {
set.type.nInput ← set.type.nInput+1;
set.inList ← CONS[thisNode, set.inList];
thisNode.setList ← CONS[set, thisNode.setList]
};
ENDLOOP;
};
FindFixedV: PROC [set: Set, fixedVList: NodeList, GndNode, VddNode: Node] ~ {
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;
IF NOT IsNodeInList[fix.first, set.fixedV] 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 [set: Set, circuit: Circuit] ~ {
no error messages for sets dealing with I/O of the chip
FOR iNodeList: NodeList ← set.inList, iNodeList.rest UNTIL iNodeList=NIL DO
IF iNodeList.first.watched THEN RETURN;
ENDLOOP;
FOR iNodeList: NodeList ← set.lNodes, iNodeList.rest UNTIL iNodeList=NIL DO
IF iNodeList.first.watched THEN RETURN;
ENDLOOP;
FOR iNodeList: NodeList ← set.lNodes, iNodeList.rest UNTIL iNodeList=NIL DO
IO.PutF[Mint.StdOut, "%g\n", IO.rope[Mint.RopeFromNode[iNodeList.first, circuit]]];
ENDLOOP;
};
CheckLibrary: PUBLIC PROC [circuit: Circuit] ~ {
n: NAT ← 0;
totalC: REAL ← 0.0;
FOR il: Library ← circuit.library, il.rest UNTIL il=NIL DO
thisSetType: SetType ← il.first.type;
thisSetList: SetList ← il.first.setList;
FOR iSetList: SetList ← thisSetList, iSetList.rest UNTIL iSetList=NIL DO
thisNodeList: NodeList ← iSetList.first.lNodes;
FOR iNodeList: NodeList ← thisNodeList, iNodeList.rest UNTIL iNodeList=NIL DO
totalC ← totalC+iNodeList.first.cap;
ENDLOOP;
ENDLOOP;
SELECT TRUE FROM
thisSetType.nFets[nE]+thisSetType.nFets[pE]=0 => {
FOR iSetList: SetList ← thisSetList, iSetList.rest UNTIL iSetList=NIL DO
thisNode: Node ← iSetList.first.lNodes.first;
IF iSetList.first.lNodes.rest#NIL THEN ERROR;
IF thisNode.flatWire.wireRoot#public THEN {
IF thisNode.setList=NIL
THEN IO.PutF[Mint.StdOut, "%g is isolated \n", IO.rope[Mint.RopeFromNode[thisNode, circuit]]]
ELSE IO.PutF[Mint.StdOut, "%g is not loaded by any fet \n", IO.rope[Mint.RopeFromNode[thisNode, circuit]]]
}
ENDLOOP;
};
thisSetType.nVddTran=0 => {
IO.PutF[Mint.StdOut, "These Nodes have no path to Vdd:\n"];
FOR iSetList: SetList ← thisSetList, iSetList.rest UNTIL iSetList=NIL DO
ErrMsg[iSetList.first, circuit];
ENDLOOP;
};
thisSetType.nGndTran=0 => {
IO.PutF[Mint.StdOut, "These Nodes have no path to Gnd:\n"];
FOR iSetList: SetList ← thisSetList, iSetList.rest UNTIL iSetList=NIL DO
ErrMsg[iSetList.first, circuit];
ENDLOOP;
};
ENDCASE;
ENDLOOP;
IO.PutF[Mint.StdOut, "total capacitance : %g \n", IO.real[totalC]];
};
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
setType: SetType ← il.first.type;
IO.PutF[Mint.StdOut, "%5d el: %5d Type: ", IO.int[n], IO.int[il.first.nElem]];
PrintSetType[Mint.StdOut, il.first.type];-- merged in to save one gfi
IO.PutF[Mint.StdOut, " %4d, %4d,", IO.int[setType.nFets[nE]], IO.int[setType.nFets[pE]]];
IO.PutF[Mint.StdOut, " %4d, %4d, %4d, %4d, \n", IO.int[setType.nVddTran], IO.int[setType.nGndTran], IO.int[setType.nNodes], IO.int[setType.nInput]];
n ← n+1;
ENDLOOP;
};
END.