RoseFromStructure.Mesa
Last Edited by: Spreitzer, July 2, 1985 7:39:05 pm PDT
DIRECTORY Asserting, CompareDataStructure, CompareOps, CompareTransforms, Convert, IO, List, OrderedSymbolTableRef, Rope, RoseTypes, RoseCreate, SwitchTypes, Transistors;
RoseFromStructure: CEDAR PROGRAM
IMPORTS Asserting, SO: CompareOps, CT: CompareTransforms, Convert, IO, List, OrderedSymbolTableRef, Rope, RoseCreate, RoseTypes, SwitchTypes, Transistors
= {OPEN S: CompareDataStructure, R: RoseTypes;
ROPE: TYPE = Rope.ROPE;
TransistorFlavor: TYPE = {n, p};
Thresholds: TYPE = REF ThresholdsRep;
ThresholdsRep: TYPE = ARRAY TransistorFlavor OF ARRAY Transistors.Mode OF RECORD [weakRatio, strongRatio: REAL];
thresholdsFn: REF ANYNEW [ROPE ← "thresholdsFn"];
MergeFromStructure: PROC [design: S.Design, thresholds: Thresholds] = {
FOR sct: S.CellType ← CT.FirstCellType[design], CT.NextCellType[sct] WHILE sct # NIL DO
cellTypeName: ROPESO.PickAName[sct.names];
oldCellType: R.CellType ← RoseCreate.GetCellType[cellTypeName];
IF oldCellType = NIL THEN ReallyDefineCellType[sct, cellTypeName, thresholds];
ENDLOOP;
thresholds ← thresholds;
};
DefineCellType: PROC [design: S.Design, cellTypeName: ROPE, thresholds: Thresholds] = {
sct: S.CellType ← SO.ToType[design, cellTypeName];
ReallyDefineCellType[sct, cellTypeName, thresholds];
};
SimpleThresholds: PROC [weakRatio: REAL ← 3.0, strongRatio: REAL ← 0.3, pFactor: REAL ← 2.5, dFactor: REAL ← 4.0] RETURNS [thresholds: Thresholds] = {
thresholds ← NEW [ThresholdsRep ← ALL[ALL[[weakRatio, strongRatio]]]];
FOR tf: TransistorFlavor IN TransistorFlavor DO
thresholds[tf][Depletion].weakRatio ← thresholds[tf][Depletion].weakRatio/dFactor;
thresholds[tf][Depletion].strongRatio ← thresholds[tf][Depletion].strongRatio/dFactor;
ENDLOOP;
FOR tm: Transistors.Mode IN Transistors.Mode DO
thresholds[p][tm].weakRatio ← thresholds[p][tm].weakRatio/pFactor;
thresholds[p][tm].strongRatio ← thresholds[p][tm].strongRatio/pFactor;
ENDLOOP;
};
ReallyDefineCellType: PROC [sct: S.CellType, cellTypeName: ROPE, thresholds: Thresholds] = {
SO.EnsureParts[sct];
SO.EnsurePorts[sct];
IF SO.ExpansionKnown[sct] THEN {
rosePorts: R.Ports ← RosePortsFromStructure[sct];
rct: R.CellType;
rct ← RoseCreate.RegisterCellType[
name: cellTypeName,
expandProc: ExpandFromStructure,
ports: rosePorts,
typeData: sct,
other: AppendAssertions[sct.otherPublic, sct.otherPrivate]];
sct.otherPrivate ← Asserting.AssertFn1[fn: thresholdsFn, val: thresholds, inAdditionTo: sct.otherPrivate];
};
};
AppendAssertions: PROC [as1, as2: Asserting.Assertions] RETURNS [as: Asserting.Assertions] =
TRUSTED {as ← LOOPHOLE[List.Append[LOOPHOLE[as1], LOOPHOLE[as2]]]};
RosePortsFromStructure: PROC [sct: S.CellType] RETURNS [rosePorts: R.Ports] = {
strPorts: S.PortS ← sct.ports;
rosePorts ← NEW [R.PortsRep[strPorts.length]];
FOR pi: NAT IN [0 .. strPorts.length) DO
portName: ROPESO.PickAName[strPorts[pi].names];
isIn: BOOL ← Asserting.Test[$IN, NIL, strPorts[pi].other];
isOut: BOOL ← Asserting.Test[$OUT, NIL, strPorts[pi].other];
isBi: BOOL ← Asserting.Test[$BIDIR, NIL, strPorts[pi].other];
isDird: BOOL ← isIn OR isOut OR isBi;
confused: BOOL ← (isIn AND isOut) OR (isOut AND isBi) OR (isBi AND isIn);
IF confused THEN SO.Warn[[], "Confused port %g", IO.rope[SO.GlobalPortName[sct, pi]]];
FOR nnl: S.RopeList ← strPorts[pi].netNames, nnl.rest WHILE nnl # NIL DO
net: S.Vertex ← NARROW[SO.Lookup[sct.parts, nnl.first]];
IF NOT SO.PickAName[net.names].Equal[portName] THEN ERROR;
ENDLOOP;
rosePorts[pi] ← [
simple: R.noField,
switch: R.noField,
name: portName,
type: SwitchTypes.bitType,
input: isIn OR isBi OR NOT isDird,
output: isOut OR isBi OR NOT isDird,
XPhobic: FALSE];
ENDLOOP;
};
ExpandFromStructure: PROC [thisCell: R.Cell, to: R.ExpansionReceiver] = {
sct: S.CellType ← NARROW[thisCell.type.typeData];
thresholds: Thresholds ← NARROW[Asserting.FnVal[fn: thresholdsFn, from: sct.otherPrivate]];
PerNode: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
v: S.Vertex ← NARROW[SO.AntiAlias[ra]];
name: ROPESO.PickAName[v.names];
already: R.Node ← RoseCreate.LookupCellNode[thisCell, name];
stop ← FALSE;
IF already # NIL THEN RETURN;
SELECT v.class FROM
net => {
other: Asserting.Assertions ← v.other;
xPhobic: BOOL ← Asserting.Test[$XPhobic, NIL, other];
xPhillic: BOOL ← Asserting.Test[$XPhillic, NIL, other];
IF NOT (xPhobic OR xPhillic) THEN other ← Asserting.AssertFn[$XPhillic, NIL, other];
other ← Asserting.AssertFn1[$DesignName, sct.design.name, other];
[] ← to.class.NodeInstance[
erInstance: to.instance,
name: name,
type: SwitchTypes.bitType,
other: other];
};
cell => NULL;
ENDCASE => ERROR};
PerCell: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
v: S.Vertex ← NARROW[SO.AntiAlias[ra]];
name: ROPESO.PickAName[v.names];
already: R.Cell ← NARROW[thisCell.components.Lookup[name]];
stop ← FALSE;
IF already # NIL THEN RETURN;
SELECT v.class FROM
net => NULL;
cell => {
typeName: ROPE;
connections: ROPE ← EncodeConnections[v];
isTrans: BOOL;
tf: TransistorFlavor;
mode: Transistors.Mode;
ratio: REAL;
[isTrans, tf, mode, ratio] ← TransistorStuff[v.type];
IF isTrans
THEN typeName ← Transistors.Transistor[[
strength: SELECT ratio FROM
>thresholds[tf][mode].weakRatio => driveWeak,
<thresholds[tf][mode].strongRatio => driveStrong,
ENDCASE => drive,
positive: tf=n,
mode: mode
]].name
ELSE typeName ← SO.PickAName[v.type.names];
[] ← to.class.CellInstance[
erInstance: to.instance,
instanceName: name,
typeName: typeName,
interfaceNodes: connections,
other: v.other];
};
ENDCASE => ERROR};
sct.parts.EnumerateIncreasing[PerNode];
sct.parts.EnumerateIncreasing[PerCell];
};
EncodeConnections: PROC [cell: S.Vertex] RETURNS [connections: ROPE] = {
connections ← NIL;
FOR e: S.Edge ← cell.firstEdge, e.sides[cell].next WHILE e # NIL DO
IF e.sides[cell].v # cell THEN ERROR;
IF connections # NIL THEN connections ← connections.Cat[", "];
connections ← connections.Cat[
Convert.RopeFromRope[SO.PickAName[cell.type.ports[e.portIndex].names]],
": ",
Convert.RopeFromRope[SO.PickAName[e.sides[net].v.names]]
];
ENDLOOP;
};
TransistorStuff: PROC [sct: S.CellType] RETURNS [isTrans: BOOL, flavor: TransistorFlavor, mode: Transistors.Mode, ratio: REAL] = {
lora, lenwid: Asserting.Terms;
len: REAL ← 2;
wid: REAL ← 2;
isTrans ← FALSE;
flavor ← n;
mode ← Enhancement;
ratio ← 1.0;
lenwid ← Asserting.FnVals[fn: $MOSFETShape, from: sct.otherPublic];
IF lenwid = NIL OR lenwid.rest = NIL OR lenwid.rest.rest # NIL THEN RETURN;
WITH lenwid.first SELECT FROM
rr: REF REAL => len ← rr^;
ri: REF INT => len ← ri^;
ENDCASE => SIGNAL R.Warning[IO.PutFR["Ill-formatted assertion ($MOSFETShape %g ..) on %g", IO.refAny[lenwid.first], IO.rope[SO.GlobalCellTypeName[sct]]]];
WITH lenwid.rest.first SELECT FROM
rr: REF REAL => wid ← rr^;
ri: REF INT => wid ← ri^;
ENDCASE => SIGNAL R.Warning[IO.PutFR["Ill-formatted assertion ($MOSFETShape .. %g) on %g", IO.refAny[lenwid.rest.first], IO.rope[SO.GlobalCellTypeName[sct]]]];
ratio ← len/wid;
lora ← Asserting.FnVals[fn: $MOSFETFlavor, from: sct.otherPublic];
IF lora = NIL THEN RETURN;
IF lora.rest = NIL OR lora.rest.rest # NIL THEN SIGNAL R.Warning[IO.PutFR[
"Ill-formatted assertion %g on %g",
IO.refAny[CONS[$MOSFETFlavor, lora]],
IO.rope[SO.GlobalCellTypeName[sct]] ]]
ELSE {
SELECT lora.first FROM
$n => flavor ← n;
$p => flavor ← p;
ENDCASE => SIGNAL R.Warning[IO.PutFR["Illegal $MOSFETFlavor type %g on %g", IO.refAny[lora.first], IO.rope[SO.GlobalCellTypeName[sct]]]];
SELECT lora.rest.first FROM
$E => mode ← Enhancement;
$D => mode ← Depletion;
ENDCASE => SIGNAL R.Warning[IO.PutFR["Illegal $MOSFETFlavor mode %g on %g", IO.refAny[lora.rest.first], IO.rope[SO.GlobalCellTypeName[sct]]]];
};
isTrans ← TRUE;
};
}.