CoreFlattenImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Spreitzer, October 2, 1985 5:03:24 pm PDT
Barth, October 2, 1985 10:36:40 am PDT
Bertrand Serlet October 2, 1985 12:26:07 pm PDT
DIRECTORY Core, CoreFlatten, CoreOps, CoreProperties, CoreRecord, CoreTransistor, IO, Rope;
CoreFlattenImpl:
CEDAR
PROGRAM
IMPORTS CoreOps, CoreProperties, CoreRecord, CoreTransistor, IO, Rope
EXPORTS CoreFlatten =
BEGIN OPEN Core, CoreRecord, CoreFlatten;
instanceSource: PUBLIC ATOM ← RegProp[$CoreFlattenInstanceSource, InstanceSourcePrint];
wireSource:
PUBLIC
ATOM ← RegProp[$CoreFlattenWireSource, WireSourcePrint];
formalToActual: ATOM ← RegProp[$CoreFlattenFormalToActual, FormalToActualPrint];
templateToCopy: ATOM ← RegProp[$CoreFlattenTemplateToCopy, TemplateToCopyPrint];
partPublic:
ATOM ← RegProp[$CoreFlattenPartPublic, PublicWirePrint];
RegProp:
PROC [prop:
ATOM, proc: CoreProperties.PropPrettyPrintProc]
RETURNS [sameProp:
ATOM] = {
sameProp ← CoreProperties.RegisterProperty[prop, CoreProperties.Props[[CoreProperties.propPrettyPrint, NEW[CoreProperties.PropPrettyPrintProc ← proc]]]];
};
InstanceSourcePrint:
PROC [to:
STREAM, prop:
ATOM, val:
REF
ANY, depth:
NAT] = {
is: InstanceSource ← NARROW[val];
InstantiationPathPrint[to, is.instantiationPath];
to.PutF[" %g:%g", IO.rope[is.instance.name], IO.rope[is.instance.type.name]];
};
InstantiationPathPrint:
PROC [to:
STREAM, instantiationPath: InstantiationPath] = {
to.PutRope["Instantiation path:"];
FOR ip: InstantiationPath ← instantiationPath, ip.rest
UNTIL ip=
NIL
DO
to.PutF[" %g:%g", IO.rope[ip.first.name], IO.rope[ip.first.type.name]];
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.publicWireFullName]]]];
};
FormalToActualPrint:
PROC [to:
STREAM, prop:
ATOM, val:
REF
ANY, depth:
NAT] = {
wire: Wire ← NARROW[val];
IO.PutF[to, "FormalToActual: %g", IO.rope[NARROW[CoreProperties.GetProp[from: wire.properties, prop: CoreOps.publicWireFullName]]]];
};
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.publicWireFullName]]]];
};
PublicWirePrint:
PROC [to:
STREAM, prop:
ATOM, val:
REF
ANY, depth:
NAT] = {
IO.PutRope[to, "PublicWire: $T"];
};
expandNonPrimitive:
PUBLIC FlattenControl ←
NEW[FlattenControlRec ← [Decide: NonPrimitiveDecide, data:
NIL]];
NonPrimitiveDecide:
PROC [data:
REF
ANY, who: InstantiationPath]
RETURNS [ExpandDecision] = {
IF who.first.type.class=CoreTransistor.transistorCellClass THEN RETURN [leaf] ELSE RETURN[expand];
};
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: RecordCellType;
promotions: Promotions ← NEW [PromotionsRec ← []];
Work:
PROC [cl: CellInstanceList, pathPrefix: InstantiationPath] = {
flat ← flat;
FOR cl ← cl, cl.rest
WHILE cl #
NIL
DO
child: 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: RecordCellType ← NARROW[childType.data];
AssocWire[key: formalToActual, from: child.type.publicWire, to: child.actualWire];
PromotePrivates[parent: flat, parentRec: newRec, child: childType, childRec: childRec, promotions: promotions, path: path];
Work[childRec.instances, path];
child ← child;
};
leaf => {
newChild: 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 # recordCellClass THEN RETURN [cellType];
[oldRec, newRec, flat] ← CopyCellType[cellType];
Work[cl: oldRec.instances, pathPrefix: NIL];
IF promotions.count # 0
THEN {
oldIW: Wire ← newRec.internalWire;
newIW: Wire ←
NEW [WireRec ← [
name: NIL,
structure: record,
elements: NEW [WireSequenceRec[oldIW.elements.size + promotions.count]],
properties: oldIW.properties
]];
i: NAT ← 0;
IF oldIW.structure # record THEN ERROR;
THROUGH [0 .. oldIW.elements.size)
DO
newIW.elements[i] ← oldIW.elements[i];
i ← i + 1;
ENDLOOP;
FOR wl: WireList ← promotions.wires, wl.rest
WHILE wl #
NIL
DO
newIW.elements[i] ← wl.first;
i ← i + 1;
ENDLOOP;
IF i # (oldIW.elements.size + promotions.count) THEN ERROR;
newRec.internalWire ← newIW;
};
};
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: RecordCellType, new: CellType] = {
oldRec ← NARROW[old.data];
newRec ←
NEW [RecordCellTypeRec ← [
internalWire: CoreOps.CopyWire[oldRec.internalWire],
instances: NIL]];
NoteWireSource[newWire: newRec.internalWire, source: [instantiationPath: NIL, wire: oldRec.internalWire, instance: NIL], recursively: TRUE];
AssocWire[key: templateToCopy, from: oldRec.internalWire, to: newRec.internalWire];
new ← NEW [CellTypeRec ← old^];
new.data ← newRec;
new.properties ← CoreProperties.CopyProps[old.properties];
new.publicWire ← DuplicatePublicWire[old.publicWire];
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 internalWire-- THEN RETURN;
newPublicWire ←
NEW [WireRec ← [
name: NIL,
structure: oldPublicWire.structure,
elements: NIL,
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 ← NEW [WireSequenceRec[oldPublicWire.elements.size]];
FOR i:
INT
IN [0 .. oldPublicWire.elements.size)
DO
newPublicWire.elements[i] ← DuplicatePublicWire[oldPublicWire.elements[i]];
ENDLOOP;
};
};
PromotePrivates:
PROC [parent: CellType, parentRec: RecordCellType, child: CellType, childRec: RecordCellType, promotions: Promotions, path: InstantiationPath] = {
FindPublic:
PROC [childsInternal: Wire]
RETURNS [somePublic:
BOOL] = {
somePublic ← GetWireAssoc[key: formalToActual, from: childsInternal] # NIL;
IF (
NOT somePublic)
AND childsInternal.structure # atom
THEN {
FOR i:
NAT
IN [0 .. childsInternal.elements.size)
DO
subWire: Wire ← childsInternal.elements[i];
subSomePublic: BOOL ← FindPublic[subWire];
somePublic ← somePublic OR subSomePublic;
ENDLOOP;
child ← child;
};
IF somePublic THEN childsInternal.properties ← CoreProperties.PutProp[on: childsInternal.properties, prop: partPublic, value: $T];
};
DoForPrivateCover:
PROC [childsInternal: Wire] = {
allPublic: BOOL ← GetWireAssoc[key: formalToActual, from: childsInternal] # NIL;
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 allPublic
THEN {
AssocToCopy[childsInternal];
}
ELSE {
FOR i:
NAT
IN [0 .. childsInternal.elements.size)
DO
DoForPrivateCover[childsInternal.elements[i]];
ENDLOOP;
};
};
AssocToCopy:
PROC [childsInternal: Wire] = {
actual: Wire ← GetWireAssoc[key: formalToActual, from: childsInternal];
copy: Wire ← GetWireAssoc[key: templateToCopy, from: actual];
IF copy #
NIL
THEN AssocWire[key: templateToCopy, from: childsInternal, to: copy]
ELSE {
FOR i:
NAT
IN [0 .. childsInternal.elements.size)
DO
AssocToCopy[childsInternal.elements[i]];
ENDLOOP;
};
};
[] ← FindPublic[childRec.internalWire];
DoForPrivateCover[childRec.internalWire];
};
CopyInstance:
PROC [old: CellInstance, path: InstantiationPath]
RETURNS [new: CellInstance] = {
CopyActual:
PROC [oldWire: Wire]
RETURNS [new: Wire] = {
new ← GetWireAssoc[templateToCopy, oldWire];
IF new # NIL THEN RETURN;
new ←
NEW [WireRec ← [
name: NIL,
structure: oldWire.structure,
elements: NIL,
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 ← NEW [WireSequenceRec[oldWire.elements.size]];
FOR i:
INT
IN [0 .. oldWire.elements.size)
DO
new.elements[i] ← CopyActual[oldWire.elements[i]];
ENDLOOP;
new ← new;
};
new ←
NEW [CellInstanceRec ← [
name: NIL,
actualWire: CopyActual[old.actualWire],
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;
};
};
ControlByFile:
PUBLIC
PROC [fileName:
ROPE]
RETURNS [control: FlattenControl] = {
ERROR
--not yet implemented--};
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: 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: 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: CellInstance]
RETURNS [IRecognizeYou:
BOOL] = {
name: ROPE = NARROW[data];
IRecognizeYou ← name.Equal[ci.name];
};
Start[];
END.