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 23, 1985 10:35:04 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] = {
-- commented by BS
is: InstanceSource ← NARROW [val];
instName: ROPE ← NARROW [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] = {
-- commented by BS
to.PutRope["Instantiation path:"];
FOR ip: InstantiationPath ← instantiationPath, ip.rest UNTIL ip=NIL DO
instName: ROPE ← NARROW [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] = {
-- commented by BS
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.
flat ← NIL; -- THIS LINE HAS BEEN ADDED AND THE REST COMMENTED BY BS November 19, 1985 11:10:56 pm PST BECAUSE I DID NOT KNOW HOW TO CONVERT THAT WHEN WE GOT RID OF WireSequence AND REPLACED A CellInstanceList BY A SEQUENCE OF CellInstance
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: Wire ← newRec.internal;
newIW: Wire ← CoreOps.CreateWire[size: 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:
BOOL ←
TRUE, quit:
BOOL ←
FALSE] = {
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 ← newRec ← NIL; new ← NIL; -- THIS LINE HAS BEEN ADDED AND THE REST COMMENTED BY BS November 19, 1985 11:10:56 pm PST BECAUSE I DID NOT KNOW HOW TO CONVERT THAT WHEN WE GOT RID OF WireSequence AND REPLACED A CellInstanceList BY A SEQUENCE OF CellInstance
oldRec ← NARROW [old.data];
newRec ← NEW [CoreClasses.RecordCellTypeRec ← [
internal: CoreOps.CopyWire[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: DuplicatePublicWire[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.size #
0
THEN {
FOR i:
INT
IN [0 .. from.size)
DO
AssocWire[key, from[i], to[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 ← CoreOps.CreateWire[oldPublicWire.size];
FOR i:
INT
IN [0 .. oldPublicWire.size)
DO
newPublicWire[i] ← GetWireAssoc[key: templateToCopy, from: oldPublicWire[i]];
IF newPublicWire[i] # NIL --means this is part of internal-- THEN LOOP;
newPublicWire[i] ← CoreOps.CreateWire[props: CoreProperties.CopyProps[propList: oldPublicWire[i].properties]];
NoteWireSource[newWire: newPublicWire[i], source: [instantiationPath: NIL, wire: oldPublicWire[i], instance: NIL], recursively: FALSE];
newPublicWire[i] ← DuplicatePublicWire[oldPublicWire[i]];
ENDLOOP;
};
PromotePrivates:
PROC [parent: CellType, parentRec: CoreClasses.RecordCellType, child: CellType, childRec: CoreClasses.RecordCellType, promotions: Promotions, path: InstantiationPath] = {
FindPublic:
PROC [childsInternal: Wire]
RETURNS [somePublic:
BOOL] = {
FOR i:
NAT
IN [0 .. childsInternal.size)
DO
subSomePublic: BOOL ← CoreProperties.GetWireProp[from: childsInternal[i], prop: allArePublic] = $T;
IF (
NOT subSomePublic)
AND childsInternal[i].size #
0
THEN {
subSomePublic ← FindPublic[childsInternal[i]];
};
IF subSomePublic THEN childsInternal[i].properties ← CoreProperties.PutProp[on: childsInternal[i].properties, prop: partPublic, value: $T];
somePublic ← somePublic OR subSomePublic;
ENDLOOP;
};
DoForPrivateCover:
PROC [childsInternal: Wire] = {
FOR i:
NAT
IN [0 .. childsInternal.size)
DO
allPublic: BOOL ← CoreProperties.GetWireProp[from: childsInternal[i], prop: allArePublic] = $T;
somePublic: BOOL ← allPublic OR (CoreProperties.GetProp[from: childsInternal[i].properties, prop: partPublic] = $T);
IF
NOT somePublic
THEN {
new: Wire ← CoreOps.CopyWire[childsInternal[i]];
NoteWireSource[newWire: new, source: [path, childsInternal[i], NIL], recursively: TRUE];
AssocWire[key: templateToCopy, from: childsInternal[i], to: new];
promotions.count ← promotions.count + 1;
promotions.wires ← CONS[new, promotions.wires];
}
ELSE IF NOT allPublic THEN DoForPrivateCover[childsInternal[i]];
ENDLOOP;
};
[] ← FindPublic[childRec.internal];
DoForPrivateCover[childRec.internal];
};
CopyInstance:
PROC [old: CoreClasses.CellInstance, path: InstantiationPath]
RETURNS [new: CoreClasses.CellInstance] = {
CopyActual:
PROC [oldWire: Wire]
RETURNS [new: Wire] = {
new ← CoreOps.CreateWire[size: oldWire.size];
FOR i:
INT
IN [0 .. oldWire.size)
DO
new[i] ← GetWireAssoc[templateToCopy, oldWire[i]];
IF new # NIL THEN LOOP;
new[i] ← CoreOps.CreateWire[props: CoreProperties.CopyProps[oldWire[i].properties]];
NoteWireSource[new[i], [path, oldWire[i], old], FALSE];
IF oldWire[i].size = 0 THEN ERROR --this recursion must ground out in a piece of already copied template--;
new[i] ← CopyActual[oldWire[i]];
ENDLOOP;
};
new ←
NEW [CoreClasses.CellInstanceRec ← [
actual: CopyActual[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.size #
0
THEN {
FOR i:
NAT
IN [0 .. newWire.size)
DO
NoteWireSource[newWire[i], [source.instantiationPath, source.wire[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] = {
-- commented by BS
ciName: ROPE = NARROW [CoreProperties.GetCellInstanceProp[ci, CoreClasses.instanceNameProp]];
name: ROPE = NARROW [data];
IRecognizeYou ← name.Equal[ciName];
};
END.