CoreFlattenImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Spreitzer, October 2, 1985 5:03:24 pm PDT
Barth, November 6, 1985 4:33:01 pm PST
Bertrand Serlet November 12, 1985 2:40:37 pm PST
DIRECTORY Core, CoreClasses, CoreFlatten, CoreOps, CoreProperties, IO, Rope;
CoreFlattenImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreOps, CoreProperties, IO, Rope
EXPORTS CoreFlatten =
BEGIN OPEN Core, CoreFlatten;
instanceSource: PUBLIC ATOM ← RegProp[$CoreFlattenInstanceSource, InstanceSourcePrint];
wireSource: PUBLIC ATOM ← RegProp[$CoreFlattenWireSource, WireSourcePrint];
templateToCopy: ATOM ← RegProp[$CoreFlattenTemplateToCopy, TemplateToCopyPrint];
partPublic: ATOM ← RegProp[$CoreFlattenPartPublic, PublicWirePrint];
allArePublic: ATOM ← RegProp[$CoreFlattenAllPublic, PublicWirePrint];
RegProp: PROC [prop: ATOM, proc: CoreProperties.PropPrintProc] RETURNS [sameProp: ATOM] = {
sameProp ← CoreProperties.RegisterProperty[prop, CoreProperties.Props[[CoreProperties.propPrint, NEW[CoreProperties.PropPrintProc ← proc]]]];
};
InstanceSourcePrint: PROC [to: STREAM, prop: ATOM, val: REF ANY, depth: NAT] = {
is: InstanceSource ← NARROW [val];
instName: ROPENARROW [CoreProperties.GetCellInstanceProp[is.instance, CoreClasses.instanceNameProp]];
InstantiationPathPrint[to, is.instantiationPath];
to.PutF[" %g:%g", IO.rope[instName], IO.rope[CoreOps.GetCellTypeName[is.instance.type]]];
};
InstantiationPathPrint: PROC [to: STREAM, instantiationPath: InstantiationPath] = {
to.PutRope["Instantiation path:"];
FOR ip: InstantiationPath ← instantiationPath, ip.rest UNTIL ip=NIL DO
instName: ROPENARROW [CoreProperties.GetCellInstanceProp[ip.first, CoreClasses.instanceNameProp]];
to.PutF[" %g:%g", IO.rope[instName], IO.rope[CoreOps.GetCellTypeName[ip.first.type]]];
ENDLOOP;
};
WireSourcePrint: PROC [to: STREAM, prop: ATOM, val: REF ANY, depth: NAT] = {
ws: WireSource ← NARROW[val];
InstantiationPathPrint[to: to, instantiationPath: ws.instantiationPath];
IO.PutF[to, ", wire: %g", IO.rope[NARROW[CoreProperties.GetProp[from: ws.wire.properties, prop: CoreOps.publicFullName]]]];
};
TemplateToCopyPrint: PROC [to: STREAM, prop: ATOM, val: REF ANY, depth: NAT] = {
wire: Wire ← NARROW[val];
IO.PutF[to, "TemplateToCopy: %g", IO.rope[NARROW[CoreProperties.GetProp[from: wire.properties, prop: CoreOps.publicFullName]]]];
};
PublicWirePrint: PROC [to: STREAM, prop: ATOM, val: REF ANY, depth: NAT] = {
IO.PutRope[to, "PublicWire: $T"];
};
Promotions: TYPE = REF PromotionsRec;
PromotionsRec: TYPE = RECORD [
count: NAT ← 0,
wires: WireList ← NIL];
WireList: TYPE = LIST OF Wire;
Flatten: PUBLIC PROC [cellType: CellType, control: FlattenControl] RETURNS [flat: CellType] = {
Each descendent is expanded or not, depending on what control says.
oldRec, newRec: CoreClasses.RecordCellType;
promotions: Promotions ← NEW [PromotionsRec ← []];
Work: PROC [cl: CoreClasses.CellInstanceList, pathPrefix: InstantiationPath] = {
flat ← flat;
FOR cl ← cl, cl.rest WHILE cl # NIL DO
child: CoreClasses.CellInstance ← cl.first;
path: InstantiationPath ← CONS[child, pathPrefix];
SELECT control.Decide[data: control.data, who: path] FROM
expand => {
childType: CellType ← Recordify[ct: child.type];
childRec: CoreClasses.RecordCellType ← NARROW[childType.data];
IF CoreOps.VisitBinding[public: childType.public, actual: child.actual, eachWirePair: CopyTemplateMarkPublic] THEN ERROR;
PromotePrivates[parent: flat, parentRec: newRec, child: childType, childRec: childRec, promotions: promotions, path: path];
Work[childRec.instances, path];
child ← child;
};
leaf => {
newChild: CoreClasses.CellInstance ← CopyInstance[old: child, path: pathPrefix];
newRec.instances ← CONS[newChild, newRec.instances];
};
ENDCASE => ERROR;
child ← child;
ENDLOOP;
flat ← flat;
};
cellType ← Recordify[cellType];
IF cellType.class # CoreClasses.recordCellClass THEN RETURN [cellType];
[oldRec, newRec, flat] ← CopyCellType[cellType];
Work[cl: oldRec.instances, pathPrefix: NIL];
IF promotions.count # 0 THEN {
oldIW: WireSequence ← newRec.internal;
newIW: WireSequence ← NEW [WireSequenceRec[oldIW.size + promotions.count]];
i: NAT ← 0;
IF oldIW=NIL THEN ERROR;
THROUGH [0 .. oldIW.size) DO
newIW[i] ← oldIW[i];
i ← i + 1;
ENDLOOP;
FOR wl: WireList ← promotions.wires, wl.rest WHILE wl # NIL DO
newIW[i] ← wl.first;
i ← i + 1;
ENDLOOP;
IF i # (oldIW.size + promotions.count) THEN ERROR;
newRec.internal ← newIW;
};
};
CopyTemplateMarkPublic: PROC [actualWire, publicWire: Wire] RETURNS [subWires: BOOLTRUE, quit: BOOLFALSE] = {
template: REF ANY ← CoreProperties.GetWireProp[from: actualWire, prop: templateToCopy];
IF template#NIL THEN CoreProperties.PutWireProp[on: publicWire, prop: templateToCopy, value: template];
CoreProperties.PutWireProp[on: publicWire, prop: allArePublic, value: $T];
};
Recordify: PROC [ct: CellType] RETURNS [rct: CellType] = {
FOR
rct ← ct, CoreOps.Recast[rct]
UNTIL rct.class.recast = NIL
rct.class.recast = NIL exactly when rct is a record or atomic.
DO NULL ENDLOOP;
rct ← rct
};
CopyCellType: PROC [old: CellType] RETURNS [oldRec, newRec: CoreClasses.RecordCellType, new: CellType] = {
oldRec ← NARROW [old.data];
newRec ← NEW [CoreClasses.RecordCellTypeRec ← [
internal: CoreOps.CopyWireSequence[oldRec.internal],
instances: NIL]];
FOR i: NAT IN [0 .. newRec.internal.size) DO
NoteWireSource[newWire: newRec.internal[i], source: [instantiationPath: NIL, wire: oldRec.internal[i], instance: NIL], recursively: TRUE];
AssocWire[key: templateToCopy, from: oldRec.internal[i], to: newRec.internal[i]];
ENDLOOP;
new ← CoreOps.CreateCellType[
class: old.class,
public: DuplicatePublicWireSequence[old.public],
data: newRec,
props: CoreProperties.CopyProps[old.properties]
];
new ← new
};
AssocWire: PROC [key: ATOM, from, to: Wire] = {
from.properties ← CoreProperties.PutProp[on: from.properties, prop: key, value: to];
IF from.elements # NIL THEN {
FOR i: INT IN [0 .. from.elements.size) DO
AssocWire[key, from.elements[i], to.elements[i]];
ENDLOOP;
key ← key
};
};
GetWireAssoc: PROC [key: ATOM, from: Wire] RETURNS [to: Wire] =
{to ← NARROW[CoreProperties.GetProp[from: from.properties, prop: key]]};
DuplicatePublicWire: PROC [oldPublicWire: Wire] RETURNS [newPublicWire: Wire] = {
newPublicWire ← GetWireAssoc[key: templateToCopy, from: oldPublicWire];
IF newPublicWire # NIL --means this is part of internal-- THEN RETURN;
newPublicWire ← NEW [WireRec ← [
properties: CoreProperties.CopyProps[propList: oldPublicWire.properties]
]];
NoteWireSource[newWire: newPublicWire, source: [instantiationPath: NIL, wire: oldPublicWire, instance: NIL], recursively: FALSE];
IF oldPublicWire.elements # NIL THEN newPublicWire.elements ← DuplicatePublicWireSequence[oldPublicWire.elements];
};
DuplicatePublicWireSequence: PROC [oldPublicWire: WireSequence] RETURNS [newPublicWire: WireSequence] = {
newPublicWire ← NEW [WireSequenceRec[oldPublicWire.size]];
FOR i: INT IN [0 .. oldPublicWire.size) DO
newPublicWire[i] ← DuplicatePublicWire[oldPublicWire[i]];
ENDLOOP;
};
PromotePrivates: PROC [parent: CellType, parentRec: CoreClasses.RecordCellType, child: CellType, childRec: CoreClasses.RecordCellType, promotions: Promotions, path: InstantiationPath] = {
FindPublicSequence: PROC [childsInternal: WireSequence] RETURNS [somePublic: BOOL] = {
FOR i: NAT IN [0 .. childsInternal.size) DO
subWire: Wire ← childsInternal[i];
subSomePublic: BOOL ← FindPublic[subWire];
somePublic ← somePublic OR subSomePublic;
ENDLOOP;
};
FindPublic: PROC [childsInternal: Wire] RETURNS [somePublic: BOOL] = {
somePublic ← CoreProperties.GetWireProp[from: childsInternal, prop: allArePublic] = $T;
IF (NOT somePublic) AND childsInternal.elements # NIL THEN {
somePublic ← FindPublicSequence[childsInternal.elements];
child ← child;
};
IF somePublic THEN childsInternal.properties ← CoreProperties.PutProp[on: childsInternal.properties, prop: partPublic, value: $T];
};
DoForPrivateCoverSequence: PROC [childsInternal: WireSequence] = {
FOR i: NAT IN [0 .. childsInternal.size) DO
DoForPrivateCover[childsInternal[i]];
ENDLOOP;
};
DoForPrivateCover: PROC [childsInternal: Wire] = {
allPublic: BOOL ← CoreProperties.GetWireProp[from: childsInternal, prop: allArePublic] = $T;
somePublic: BOOL ← allPublic OR (CoreProperties.GetProp[from: childsInternal.properties, prop: partPublic] = $T);
IF NOT somePublic THEN {
new: Wire ← CoreOps.CopyWire[childsInternal];
NoteWireSource[newWire: new, source: [path, childsInternal, NIL], recursively: TRUE];
AssocWire[key: templateToCopy, from: childsInternal, to: new];
promotions.count ← promotions.count + 1;
promotions.wires ← CONS[new, promotions.wires];
}
ELSE IF NOT allPublic THEN DoForPrivateCoverSequence[childsInternal.elements];
};
[] ← FindPublicSequence[childRec.internal];
DoForPrivateCoverSequence[childRec.internal];
};
CopyInstance: PROC [old: CoreClasses.CellInstance, path: InstantiationPath] RETURNS [new: CoreClasses.CellInstance] = {
CopyActualSequence: PROC [oldWire: WireSequence] RETURNS [new: WireSequence] = {
new ← NEW [WireSequenceRec[oldWire.size]];
FOR i: INT IN [0 .. oldWire.size) DO
new[i] ← CopyActual[oldWire[i]];
ENDLOOP;
};
CopyActual: PROC [oldWire: Wire] RETURNS [new: Wire] = {
new ← GetWireAssoc[templateToCopy, oldWire];
IF new # NIL THEN RETURN;
new ← NEW [WireRec ← [
properties: CoreProperties.CopyProps[oldWire.properties]
]];
NoteWireSource[new, [path, oldWire, old], FALSE];
IF oldWire.elements = NIL THEN ERROR --this recursion must ground out in a piece of already copied template--;
new.elements ← CopyActualSequence[oldWire.elements];
new ← new;
};
new ← NEW [CoreClasses.CellInstanceRec ← [
actual: CopyActualSequence[old.actual],
type: old.type,
properties: CoreProperties.CopyProps[old.properties]
]];
new.properties ← CoreProperties.PutProp[on: new.properties, prop: instanceSource, value: NEW[InstanceSourceRec ← [path, old]]];
};
NoteWireSource: PROC [newWire: Wire, source: WireSourceRec, recursively: BOOL] = {
newWire.properties ← CoreProperties.PutProp[on: newWire.properties, prop: wireSource, value: NEW [WireSourceRec ← source] ];
IF recursively AND newWire.elements # NIL THEN {
FOR i: NAT IN [0 .. newWire.elements.size) DO
NoteWireSource[newWire.elements[i], [source.instantiationPath, source.wire.elements[i], source.instance], recursively];
ENDLOOP;
newWire ← newWire;
};
};
ExpandNonPrimitive: PUBLIC FlattenControl ← NEW[FlattenControlRec ← [Decide: NonPrimitiveDecide, data: NIL]];
NonPrimitiveDecide: PROC [data: REF ANY, who: InstantiationPath] RETURNS [ExpandDecision] = {
IF who.first.type.class=CoreClasses.transistorCellClass THEN RETURN [leaf] ELSE RETURN[expand];
};
ControlByCutSet: PUBLIC PROC [cutSetName: ROPE] RETURNS [control: FlattenControl] = {
control ← NEW [FlattenControlRec ← [Decide: DecideByCutSet, data: cutSetName]];
};
CoreFlattenCutSets: PUBLIC ATOM ← CoreProperties.RegisterProperty[prop: $CoreFlattenCutSets];
DecideByCutSet: PROC [data: REF ANY, who: InstantiationPath] RETURNS [ExpandDecision] = {
cutSetName: ROPE;
cutSets: LIST OF REF;
IF who.first.type.class=CoreClasses.transistorCellClass THEN RETURN [leaf];
IF Rope.Equal[CoreOps.GetCellTypeName[who.first.type], "DataBuffer"] THEN {
cutSetName ← NARROW[data];
};
cutSetName ← NARROW[data];
cutSets ← NARROW[CoreProperties.GetCellInstanceProp[from: who.first, prop: CoreFlattenCutSets]];
IF cutSets=NIL THEN cutSets ← NARROW[CoreProperties.GetCellTypeProp[from: who.first.type, prop: CoreFlattenCutSets]];
IF cutSets=NIL THEN RETURN[expand];
FOR csl: LIST OF REF ← cutSets, csl.rest UNTIL csl=NIL DO
IF Rope.Equal[FixStupidRef[csl.first], cutSetName] THEN RETURN[leaf];
ENDLOOP;
RETURN[expand];
};
FixStupidRef: PROC [ref: REF ANY] RETURNS [rope: ROPE] = {
rope ← WITH ref SELECT FROM
r: REF TEXT => Rope.FromRefText[r],
r: ROPE => r,
ENDCASE => ERROR;
};
ControlByRecognition: PUBLIC PROC [rl: RecognitionList] RETURNS [control: FlattenControl] = {
control ← NEW [FlattenControlRec ← [Decide: DecideByRecognition, data: rl]];
};
DecideByRecognition: PROC [data: REF ANY, who: InstantiationPath] RETURNS [ExpandDecision] = {
rl: RecognitionList ← NARROW[data];
shallowest: CoreClasses.CellInstance ← GetShallowest[who];
FOR rl ← rl, rl.rest WHILE rl # NIL DO
IF rl.first.recognizer.Recognize[rl.first.recognizer.data, shallowest]
THEN WITH rl.first SELECT FROM
i: Recognition.immediate => RETURN [i.decision];
n: Recognition.nest => {
subPath: InstantiationPath ← AllButShallowest[who];
decision: ExpandDecision ← n.subControl.Decide[n.subControl.data, subPath];
RETURN [decision];
};
ENDCASE => ERROR;
ENDLOOP;
ERROR;
};
GetShallowest: PUBLIC PROC [path: InstantiationPath] RETURNS [shallowest: CoreClasses.CellInstance] = {
FOR path ← path, path.rest WHILE path # NIL DO shallowest ← path.first ENDLOOP;
};
AllButShallowest: PUBLIC PROC [path: InstantiationPath] RETURNS [allBut: InstantiationPath] = {
first, last: InstantiationPath ← NIL;
FOR path ← path, path.rest WHILE path.rest # NIL DO
this: InstantiationPath ← LIST[path.first];
IF last # NIL THEN last.rest ← this ELSE first ← this;
last ← this;
ENDLOOP;
allBut ← first;
};
RecognizeName: PUBLIC PROC [name: ROPE] RETURNS [r: Recognizer] = {
r ← NEW [RecognizerRec ← [DoRecognizeName, name]];
};
DoRecognizeName: PROC [data: REF ANY, ci: CoreClasses.CellInstance] RETURNS [IRecognizeYou: BOOL] = {
ciName: ROPE = NARROW [CoreProperties.GetCellInstanceProp[ci, CoreClasses.instanceNameProp]];
name: ROPE = NARROW [data];
IRecognizeYou ← name.Equal[ciName];
};
END.