LichenSpecialTransforms:
CEDAR
PROGRAM
IMPORTS LichenDataStructure, LichenOps, LichenTransforms, LichenTransformsPrivate, RedBlackTree, RedBlackTreeExtras, RefTab, Rope, TextReplace
EXPORTS LichenTransforms, LichenOps, LichenTransformsPrivate =
BEGIN OPEN LichenDataStructure, LichenTransforms, LichenOps, LichenTransformsPrivate;
Special: TYPE = REF SpecialRep;
SpecialRep: TYPE = RECORD [ra: REF ANY];
all: PUBLIC REF ANY ← NEW [SpecialRep ← [$all]];
ExpandVertex:
PUBLIC
PROC [design: Design, childA:
REF
ANY] =
BEGIN
child: Vertex ← ToVertex[design, childA];
parentType: CellType ← child.parent;
childType: CellType ← child.type;
[] ← ExpandVertexWork[child];
NoteChange[parentType];
CheckType[parentType, ignore, ignore];
CheckType[childType, ignore, ignore];
END;
igig: LORA ← LIST[$ignore, $ignore];
ExpandChildren:
PUBLIC
PROC [design: Design, parentTypeA:
REF
ANY, flatten:
BOOL ←
FALSE] =
BEGIN
parentType: CellType ← ToType[design, parentTypeA];
childTypes: RefTab.Ref ← RefTab.Create[];
children: RefTab.Ref ← RefTab.Create[];
NoteOldChild:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
[] ← children.Insert[v, $T];
stop ← FALSE};
ExpandOldChild:
PROC [key, val:
REF
ANY]
RETURNS [quit:
BOOL] = {
v: Vertex ← NARROW[key];
quit ← FALSE;
SELECT v.class
FROM
cell => {
childType: CellType ← v.type;
EnsureParts[childType];
IF ExpansionKnown[childType]
THEN {
sibs: VertexList ← ExpandVertexWork[v];
[] ← childTypes.Insert[childType, igig];
IF flatten
THEN {
FOR sibs ← sibs, sibs.rest
WHILE sibs #
NIL
DO
[] ← ExpandOldChild[sibs.first, NIL];
ENDLOOP;
};
};
};
net => NULL;
ENDCASE => ERROR;
};
EnsureParts[parentType];
IF NOT ExpansionKnown[parentType] THEN ERROR;
parentType.parts.EnumerateIncreasing[NoteOldChild];
[] ← children.Pairs[ExpandOldChild];
NoteChange[parentType];
CheckType[parentType, ignore, ignore];
[] ← childTypes.Pairs[CheckPerType];
END;
ExpandVertexWork:
PROC [childCell: Vertex]
RETURNS [newSibs: VertexList] =
BEGIN
parentType: CellType ← childCell.parent;
childType: CellType ← childCell.type;
NILEquiv:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
stop ← FALSE;
v.equiv ← NIL};
SetPortedNetEquivs:
PROC = {
innerEdge: Edge ← childType.mirror.firstEdge;
outerEdge: Edge ← childCell.firstEdge;
FOR portIndex:
NAT
IN [0 .. childType.ports.length)
DO
IF innerEdge.portIndex # portIndex THEN ERROR;
IF outerEdge.portIndex # portIndex THEN ERROR;
IF innerEdge.sides[cell].v # childType.mirror THEN ERROR;
IF outerEdge.sides[cell].v # childCell THEN ERROR;
innerEdge.sides[net].v.equiv ← outerEdge.sides[net].v;
innerEdge ← innerEdge.sides[cell].next;
outerEdge ← outerEdge.sides[cell].next;
ENDLOOP;
IF innerEdge # NIL OR outerEdge # NIL THEN ERROR};
Copy:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
stop ← FALSE;
[] ← CopyWork[v]};
CopyWork:
PROC [gc: Vertex]
RETURNS [newChild: Vertex] = {
IF gc.equiv # NIL THEN RETURN [gc.equiv];
gc.equiv ← newChild ← NEW [VertexRep ← [names: JoinNames[childCell.names, gc.names], type: gc.type, parent: parentType, class: gc.class, other: gc.other]];
AddVertex[newChild];
IF newChild.class = net THEN RETURN;
LinkInstance[newChild];
FOR oldE: Edge ← gc.firstEdge, oldE.sides[cell].next
WHILE oldE #
NIL
DO
newNet: Vertex ← CopyWork[oldE.sides[net].v];
IF oldE.sides[cell].v # gc THEN ERROR;
AddEdge[newChild, newNet];
ENDLOOP;
newSibs ← CONS[newChild, newSibs];
};
newSibs ← NIL;
EnsureParts[childType];
IF NOT ExpansionKnown[childType] THEN ERROR;
childType.mirror.equiv ← NIL;
childType.parts.EnumerateIncreasing[NILEquiv];
childType.mirror.equiv ← childCell;
SetPortedNetEquivs[];
childType.parts.EnumerateIncreasing[Copy];
DeleteVertex[childCell];
childType.mirror.equiv ← NIL;
childType.parts.EnumerateIncreasing[NILEquiv];
CheckType[parentType, ignore, ignore, TRUE];
END;
Group:
PUBLIC
PROC [design: Design, parentTypeA, childrenA:
REF
ANY, childNames, childTypeNames: Names, newPortNamer: NewPortNamer]
RETURNS [newChild: Vertex, newGrandchildren: VertexS] =
BEGIN
parentType: CellType ← ToType[design, parentTypeA];
oldChildren: VertexS ← ToVertexS[parentType, childrenA];
newChildType: CellType ← NewEmptyCellType[design, childTypeNames];
newChild ← CreateEmpty[design: design, childNames: childNames, childType: newChildType, parentType: parentType];
[gcs: newGrandchildren] ← LowerChildren[design: design, childTypeA: newChildType, gcNamesl: ListNames[oldChildren], sibber: OneMap[newChild, oldChildren], newPortNamer: newPortNamer];
END;
NameNewPortFromAnyOldPort:
PUBLIC
PROC
[
data: REF ANY, first: BOOL, ct: CellType,
ports: PortS, portIndex: PortIndex,
oldNet: Vertex, oldConnections: EdgeList]
RETURNS [names: Names, equivClass: EquivClass] =
{
from: Vertex ← oldConnections.first.sides[cell].v;
index: PortIndex ← oldConnections.first.portIndex;
names ← from.type.ports[index].names;
equivClass ← from.type.ports[index].equivClass};
NameNewPortFromAnyOldPortInstance:
PUBLIC
PROC
[
data: REF ANY, first: BOOL, ct: CellType,
ports: PortS, portIndex: PortIndex,
oldNet: Vertex, oldConnections: EdgeList]
RETURNS [names: Names, equivClass: EquivClass] =
{
from: Vertex ← oldConnections.first.sides[cell].v;
index: PortIndex ← oldConnections.first.portIndex;
names ← from.type.ports[index].names;
IF NOT first THEN names ← JoinNames[from.names, names, FALSE];
equivClass ← from.type.ports[index].equivClass;
IF NOT first THEN equivClass ← QualifyEquivClass[from.names, equivClass, FALSE];
};
NameNewPortFromOldNet:
PUBLIC
PROC
[
data: REF ANY, first: BOOL, ct: CellType,
ports: PortS, portIndex: PortIndex,
oldNet: Vertex, oldConnections: EdgeList]
RETURNS [names: Names, equivClass: EquivClass] =
{
names ← oldNet.names;
equivClass ← implicitClass};
DontNameNewPort:
PUBLIC
PROC
[
data: REF ANY, first: BOOL, ct: CellType,
ports: PortS, portIndex: PortIndex,
oldNet: Vertex, oldConnections: EdgeList]
RETURNS [names: Names, equivClass: EquivClass] =
{ERROR};
FavorSimpleNames:
PUBLIC
PROC [data:
REF
ANY, oldNames: Names, oldEquiv: EquivClass]
RETURNS [newNames: Names, newEquiv: EquivClass] = {
newNames ← oldNames;
newEquiv ← oldEquiv;
IF newNames.progged = NIL OR newNames.progged.rest = NIL THEN RETURN;
FOR rl: RopeList ← newNames.progged, rl.rest
WHILE rl #
NIL
DO
class: CARDINAL ← 0;
seeingGen:
BOOL ←
FALSE;
For detecting name segments matching {n|C|Q}{0..9}+
lastWasGen, lastWasDash, lastWasAlpha, nextLastWasAlpha: BOOL ← FALSE;
FOR i:
INT
IN [0 .. rl.first.Length[])
DO
c: CHAR ← rl.first.Fetch[i];
SELECT c
FROM
'., '- => IF seeingGen THEN class ← class + 1;
ENDCASE;
SELECT c
FROM
'. => {class ← class + 1; seeingGen ← FALSE};
IN ['0 .. '9] => {
IF lastWasDash THEN {class ← class + 1; IF seeingGen THEN ERROR};
IF lastWasGen AND NOT nextLastWasAlpha THEN seeingGen ← TRUE;
};
ENDCASE => seeingGen ← FALSE;
nextLastWasAlpha ← lastWasAlpha;
SELECT c
FROM
'., '- => lastWasAlpha ← FALSE;
ENDCASE => lastWasAlpha ← TRUE;
SELECT c
FROM
'n, 'C, 'Q => {lastWasGen ← TRUE; lastWasDash ← FALSE};
'- => {lastWasGen ← FALSE; lastWasDash ← TRUE};
ENDCASE => lastWasGen ← lastWasDash ← FALSE;
ENDLOOP;
IF seeingGen THEN class ← class + 1;
classes[MIN[WorstClass, class]].Insert[rl.first, rl.first];
ENDLOOP;
newNames.progged ← NIL;
FOR c:
CARDINAL
IN [0 .. WorstClass]
DO
name: ROPE ← NARROW[classes[c].LookupLargest[]];
IF name = NIL THEN LOOP;
WHILE name #
NIL
DO
newNames.progged ← CONS[name, newNames.progged];
name ← NARROW[classes[c].LookupNextSmaller[name]];
ENDLOOP;
FOR d: CARDINAL IN [c .. WorstClass] DO classes[d].DestroyTable[] ENDLOOP;
EXIT;
ENDLOOP;
IF newNames.progged = NIL THEN ERROR;
};
WorstClass: CARDINAL ~ 8;
classes: ARRAY [0 .. WorstClass] OF SymbolTable;
InitClasses:
PROC = {
FOR c: CARDINAL IN [0 .. WorstClass] DO classes[c] ← RedBlackTree.Create[GetIDKey, CompareRopes] ENDLOOP;
};
ReNameByName:
PUBLIC
PROC [rm: RopeMap]
RETURNS [r: Renamer] = {
r ← [rm, RenameByName];
};
RenameByName:
PROC [data:
REF
ANY, oldNames: Names, oldEquiv: EquivClass]
RETURNS [newNames: Names, newEquiv: EquivClass] = {
rm: RopeMap ← NARROW[data];
diff: BOOL ← FALSE;
RenameRope:
PROC [old:
ROPE]
RETURNS [new:
ROPE] = {
new ← rm.Apply[old];
diff ← diff OR NOT new.Equal[old];
};
RenameList:
PROC [old: RopeList]
RETURNS [new: RopeList] = {
newTail: RopeList ← new ← NIL;
FOR old ← old, old.rest
WHILE old #
NIL
DO
[new, newTail] ← RopeListCat[RenameRope[old.first], new, newTail];
ENDLOOP;
};
newEquiv ← RenameRope[oldEquiv];
newNames.designed ← RenameList[oldNames.designed];
newNames.unknown ← RenameList[oldNames.unknown];
newNames.progged ← RenameList[oldNames.progged];
IF NOT diff THEN RETURN [oldNames, oldEquiv];
};
MapRopePairs:
PUBLIC
PROC [pairs: RopePairList]
RETURNS [rm: RopeMap] = {
st: SymbolTableHolder ← NEW [SymbolTable ← RedBlackTree.Create[GetPairKey, ComparePairs]];
FOR pairs ← pairs, pairs.rest
WHILE pairs #
NIL
DO
st^.Insert[pairs, pairs.first.old];
ENDLOOP;
rm ← NEW [TextReplace.RopeMapRep ← [MapByPairs, st]];
};
GetPairKey:
PROC [data:
REF
ANY]
RETURNS [key:
ROPE]
--RedBlackTree.GetKey-- =
{p: RopePairList ← NARROW[data]; key ← p.first.old};
ComparePairs:
PROC [k, data:
REF
ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- = {
k1: ROPE ← NARROW[k];
k2: ROPE ← GetPairKey[data];
c ← k1.Compare[k2];
};
MapByPairs:
PROC [data:
REF
ANY, old:
ROPE]
RETURNS [new:
ROPE] = {
st: SymbolTableHolder ← NARROW[data];
p: RopePairList ← NARROW[st^.Lookup[old]];
new ← IF p # NIL THEN p.first.new ELSE old;
};
RenamePairs:
PUBLIC
PROC [pairs: RopePairList]
RETURNS [r: Renamer] = {
r ← ReNameByName[MapRopePairs[pairs]];
};
Setter: TYPE = REF SetterRep;
SetterRep: TYPE = RECORD [names: Names, equivClass: EquivClass];
useOldNames: PUBLIC Names ← [LIST["use old designed"], LIST["use old unknown"], LIST["use old progged"]];
useOldEquivClass: PUBLIC ROPE ← "use old equiv class";
SetNames:
PUBLIC
PROC [names: Names ← useOldNames, equivClass: EquivClass ← useOldEquivClass]
RETURNS [r: Renamer] = {
r ← [NEW [SetterRep ← [names, equivClass]], DoSetNames];
};
DoSetNames:
PROC [data:
REF
ANY, oldNames: Names, oldEquiv: EquivClass]
RETURNS [newNames: Names, newEquiv: EquivClass] = {
s: Setter ← NARROW[data];
newNames ← IF s.names = useOldNames THEN oldNames ELSE s.names;
newEquiv ← IF s.equivClass = useOldEquivClass THEN oldEquiv ELSE s.equivClass;
};
RopeListCat:
PROC [rope:
ROPE, oldHead, oldTail: RopeList]
RETURNS [newHead, newTail: RopeList] = {
newHead ← oldHead;
newTail ← LIST[rope];
IF oldTail # NIL THEN oldTail.rest ← newTail ELSE newHead ← newTail;
};
CellTypePair: TYPE = REF CellTypePairRep;
CellTypePairRep: TYPE = RECORD [ct1, ct2: CellType];
ChildrenOfType:
PUBLIC
PROC [design: Design, parentTypeA, childTypeA:
REF
ANY]
RETURNS [bag: Bag] = {
parentType: CellType ← ToType[design, parentTypeA];
childType: CellType ← ToType[design, childTypeA];
bag ←
NEW [BagRep ← [
data: NEW [CellTypePairRep ← [parentType, childType]],
Enumerate: EnumerateTypedChildren ]];
};
ImplicitChildrenOfType:
PUBLIC
PROC [design: Design, childTypeA:
REF
ANY]
RETURNS [bag: Bag] = {
childType: CellType ← ToType[design, childTypeA];
bag ←
NEW [BagRep ← [
data: NEW [CellTypePairRep ← [implicitType, childType]],
Enumerate: EnumerateTypedChildren ]];
};
implicitType: CellType ← NEW [CellTypeRep ← [design: NIL, names: [designed: LIST["implicitType"]] ]];
EnumerateTypedChildren:
PROC [context, data:
REF
ANY, to:
PROC [
REF
ANY]] = {
PerChild:
PROC [ra:
REF
ANY]
RETURNS [quit:
BOOL] = {
a: Alias ← NARROW[ra];
v: Vertex ← NARROW[AntiAlias[a]];
quit ← FALSE;
IF a.name # PickAName[v.names] THEN RETURN;
SELECT v.class
FROM
net => RETURN;
cell => NULL;
ENDCASE => ERROR;
IF v.type = childType THEN to[v];
};
ctp: CellTypePair ← NARROW[data];
parentType: CellType ← IF ctp.ct1 # implicitType THEN ctp.ct1 ELSE NARROW[context];
childType: CellType ← ctp.ct2;
RedBlackTreeExtras.StatelessEnumerateIncreasing[parentType.parts, PerChild, GetAliasKey];
};
FirstCellType:
PUBLIC
PROC [design: Design]
RETURNS [ct: CellType] = {
ct ← NARROW[design.cellTypesByAddress.LookupSmallest[]];
};
NextCellType:
PUBLIC
PROC [prev: CellType]
RETURNS [next: CellType] = {
next ← NARROW[prev.design.cellTypesByAddress.LookupNextLarger[prev]];
};
EnumerateCellTypes:
PUBLIC
PROC [design: Design, ra:
REF
ANY, consume:
PROC [CellType]] = {
EatAny:
PROC [ra:
REF
ANY] = {
ct: CellType ← NARROW[ra];
consume[ct]};
WITH ra
SELECT
FROM
cl:
LIST
OF CellType =>
FOR l:
LIST
OF CellType ← cl, l.rest
WHILE l #
NIL
DO
consume[l.first]
ENDLOOP;
lora:
LORA =>
FOR l:
LORA ← lora, l.rest
WHILE l #
NIL
DO
consume[ToType[design, l.first]]
ENDLOOP;
bag: Bag => {
bag.Enumerate[design, bag.data, EatAny];
};
ENDCASE => ERROR};
EnumerateParts:
PUBLIC
PROC [ct: CellType, consume:
PROC [Vertex]] = {
PerPart:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
a: Alias ← NARROW[ra];
v: Vertex ← NARROW[AntiAlias[a]];
stop ← FALSE;
IF a.name.Equal[PickAName[v.names]] THEN consume[v];
};
RedBlackTreeExtras.StatelessEnumerateIncreasing[ct.parts, PerPart, GetAliasKey];
};
EnumerateVertices:
PUBLIC
PROC [context, ra:
REF
ANY, consume:
PROC [Vertex]] = {
EatAny:
PROC [ra:
REF
ANY] = {
v: Vertex ← NARROW[ra];
consume[v]};
PerPart:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
a: Alias ← NARROW[ra];
v: Vertex ← NARROW[AntiAlias[a]];
IF PickAName[v.names] = a.name THEN consume[v];
stop ← FALSE};
WITH ra
SELECT
FROM
vl: VertexList =>
FOR l: VertexList ← vl, l.rest
WHILE l #
NIL
DO
consume[l.first]
ENDLOOP;
lora:
LORA =>
FOR l:
LORA ← lora, l.rest
WHILE l #
NIL
DO
consume[ToVertex[context, l.first]]
ENDLOOP;
bag: Bag => {
bag.Enumerate[context, bag.data, EatAny];
};
s: Special =>
SELECT s.ra
FROM
$all => {ct: CellType ←
NARROW[context];
EnsureParts[ct];
IF NOT ExpansionKnown[ct] THEN ERROR;
RedBlackTreeExtras.StatelessEnumerateIncreasing[ct.parts, PerPart, GetAliasKey]};
ENDCASE => ERROR;
ENDCASE => ERROR};
UnlinkInstance:
PUBLIC
PROC [v: Vertex] = {
IF v.prevInstance # NIL THEN v.prevInstance.nextInstance ← v.nextInstance ELSE v.type.firstInstance ← v.nextInstance;
IF v.nextInstance # NIL THEN v.nextInstance.prevInstance ← v.prevInstance ELSE v.type.lastInstance ← v.prevInstance;
};
LinkInstance:
PUBLIC
PROC [v: Vertex] = {
v.nextInstance ← NIL;
v.prevInstance ← v.type.lastInstance;
IF v.prevInstance # NIL THEN v.prevInstance.nextInstance ← v ELSE v.type.firstInstance ← v;
IF v.nextInstance # NIL THEN v.nextInstance.prevInstance ← v ELSE v.type.lastInstance ← v;
};
DeleteVertex:
PUBLIC
PROC [v: Vertex] = {
v ← v;
WHILE v.firstEdge # NIL DO RemoveEdge[v.firstEdge] ENDLOOP;
Delete[v.parent.parts, v.names, v];
SELECT v.class
FROM
net => v.parent.netCount ← v.parent.netCount - 1;
cell => {v.parent.cellCount ← v.parent.cellCount - 1;
UnlinkInstance[v]};
ENDCASE => ERROR;
v ← v};
RemoveEdge:
PUBLIC
PROC [e: Edge] = {
UnlinkSide:
PROC [side: VertexClass] = {
head: Vertex ← e.sides[side].v;
IF e.sides[side].next #
NIL
THEN e.sides[side].next.sides[side].prev ← e.sides[side].prev
ELSE head.lastEdge ← e.sides[side].prev;
IF e.sides[side].prev #
NIL
THEN e.sides[side].prev.sides[side].next ← e.sides[side].next
ELSE head.firstEdge ← e.sides[side].next;
e.sides[side].next ← e.sides[side].prev ← badEdge};
UnlinkSide[net];
UnlinkSide[cell];
};
badEdge: PUBLIC Edge ← NEW [EdgeRep ← [sides: [[NIL, NIL, NIL], [NIL, NIL, NIL]], color: 0, portIndex: NullPortIndex]];
InitClasses[];
END.