RoseFromStructure:
CEDAR
PROGRAM
IMPORTS Asserting, Convert, IO, SO: LichenOps, CT: LichenTransforms, List, RedBlackTree, Rope, RoseCreate, RoseTypes, SwitchTypes, Transistors
= {OPEN S: LichenDataStructure, 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 ANY ← NEW [ROPE ← "thresholdsFn"];
MergeFromStructure:
PROC [design:
S.Design, thresholds: Thresholds] = {
FOR sct:
S.CellType ←
CT.FirstCellType[design],
CT.NextCellType[sct]
WHILE sct #
NIL
DO
cellTypeName: ROPE ← SO.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: ROPE ← SO.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: ROPE ← SO.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: ROPE ← SO.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;
};
}.