RoseFromStructure:
CEDAR
PROGRAM
IMPORTS Asserting, SO: CompareOps, CT: CompareTransforms, Convert, IO, OrderedSymbolTableRef, Rope, RoseCreate, RoseTypes, SwitchTypes, Transistors
= {OPEN S: CompareDataStructure, R: RoseTypes;
ROPE: TYPE = Rope.ROPE;
GenericIO: TYPE = REF GenericIORep;
GenericIORep:
TYPE =
RECORD [
ports: SEQUENCE COMPUTED CARDINAL OF SwitchTypes.SwitchValHolder];
Thresholds: TYPE = REF ThresholdsRep;
ThresholdsRep:
TYPE =
RECORD [
weakRatio, strongRatio: REAL];
thresholdsFn: REF ANY ← NEW [ROPE ← "thresholdsFn"];
MergeFromStructure:
PROC [design:
S.Design, weakRatio:
REAL ← 3.0, strongRatio:
REAL ← 0.3] = {
thresholds: Thresholds ← NEW [ThresholdsRep ← [weakRatio, strongRatio]];
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 {
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,
ioCreator: CreateIOForStructure,
evals: [],
ports: rosePorts,
typeData: sct];
sct.otherPrivate ← Asserting.AssertFn1[fn: thresholdsFn, val: thresholds, inAdditionTo: sct.otherPrivate];
};
};
ENDLOOP;
weakRatio ← weakRatio;
};
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] ← [
firstWord: pi,
wordCount: SwitchTypes.wordsPerSwitchValPort,
name: portName,
type: SwitchTypes.bitType,
input: isIn OR isBi OR NOT isDird,
output: isOut OR isBi OR NOT isDird,
XPhobic: FALSE];
ENDLOOP;
};
CreateIOForStructure:
PROC [cell:
R.Cell] = {
sct: S.CellType ← NARROW[cell.type.typeData];
cell.realCellStuff.newIO ← NEW [GenericIORep[sct.ports.length]];
cell.realCellStuff.oldIO ← NEW [GenericIORep[sct.ports.length]];
cell.realCellStuff.switchIO ← NEW [GenericIORep[sct.ports.length]];
};
ExpandFromStructure:
PROC [thisCell:
R.Cell, to:
R.ExpansionReceiver] = {
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 => {
[] ← to.class.NodeInstance[
erInstance: to.instance,
name: name,
type: SwitchTypes.bitType];
};
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;
nType: BOOL;
mode: Transistors.Mode;
ratio: REAL;
[isTrans, nType, mode, ratio] ← TransistorStuff[v.type];
IF isTrans
THEN typeName ← Transistors.Transistor[[
strength:
SELECT ratio
FROM
>thresholds.weakRatio => driveWeak,
<thresholds.strongRatio => driveStrong,
ENDCASE => drive,
positive: nType,
mode: mode
]].name
ELSE typeName ← SO.PickAName[v.type.names];
[] ← to.class.CellInstance[
erInstance: to.instance,
instanceName: name,
typeName: typeName,
interfaceNodes: connections];
};
ENDCASE => ERROR};
sct: S.CellType ← NARROW[thisCell.type.typeData];
thresholds: Thresholds ← NARROW[Asserting.FnVal[fn: thresholdsFn, from: sct.otherPrivate]];
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, nType:
BOOL, mode: Transistors.Mode, ratio:
REAL] = {
ra: REF ANY;
lora: Asserting.Terms;
isTrans ← FALSE;
nType ← TRUE;
mode ← Enhancement;
ratio ← 1.0;
ra ← Asserting.FnVal[fn: $MOSFETSquares, from: sct.otherPublic];
IF ra = NIL THEN RETURN;
WITH ra
SELECT
FROM
rr: REF REAL => ratio ← rr^;
ri: REF INT => ratio ← ri^;
ENDCASE => SIGNAL R.Warning[IO.PutFR["Ill-formatted assertion ($MOSFETSquares %g) on %g", IO.refAny[ra], IO.rope[SO.GlobalCellTypeName[sct]]]];
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 => nType ← TRUE;
$p => nType ← FALSE;
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;
};
}.