DIRECTORY LichenDataStructure, LichenOps, IO, Real, Rope; LichenCompare: CEDAR PROGRAM IMPORTS LichenOps, IO, Real, Rope EXPORTS LichenDataStructure, LichenOps = BEGIN OPEN LichenDataStructure, LichenOps; TwoCount: TYPE = ARRAY RealGraphID OF CARDINAL; graphIDToRope: PUBLIC ARRAY GraphID OF ROPE _ [A: "A", B: "B", Unspecified: "Unspecified"]; endOfQ: PUBLIC Vertex _ NEW [VertexRep]; MinHashSize: CARDINAL _ 511; sizeFactor: REAL _ 0.25; initialNetColor: Color _ 1; CompareGraphs: PUBLIC PROC [a, b: CellType, nameSee: NameSee] RETURNS [equiv: BOOL] = BEGIN ComputeColor: PROC [v: Vertex] RETURNS [color: Color] = { color _ v.oldColor; FOR e: Edge _ v.firstEdge, e.sides[v.class].next WHILE e # NIL DO nv: Vertex _ e.sides[OtherClass[v.class]].v; IF e.sides[v.class].v # v THEN ERROR; IF NOT nv.suspect THEN color _ color + (e.color+1) * (nv.oldColor+1); ENDLOOP}; EnQ: PROC [v: Vertex] = {IF (NOT v.unique) AND (v.QNext = notInQ) THEN {v.QNext _ QFirst; QFirst _ v; QCount _ QCount + 1}}; AddFrontier: PROC [v: Vertex] = { FOR e: Edge _ v.firstEdge, e.sides[v.class].next WHILE e # NIL DO IF e.sides[v.class].v # v THEN ERROR; EnQ[e.sides[OtherClass[v.class]].v]; ENDLOOP}; Initialize: PROC = { InitVertex: PROC [key, value: REF ANY] RETURNS [quit: BOOLEAN _ FALSE] --HashTable.EachPairAction-- = { v: Vertex; WITH value SELECT FROM x: Vertex => v _ x; ENDCASE => ERROR; v.graph _ curGraph; IF v.unique OR v.QNext # notInQ THEN ERROR; v.equiv _ NIL; v.suspect _ FALSE; SELECT v.class FROM net => v.curColor _ initialNetColor; cell => { portIndex: PortIndex _ 0; v.curColor _ v.type.color; FOR e: Edge _ v.firstEdge, e.sides[cell].next WHILE e # NIL DO IF e.sides[cell].v # v THEN ERROR; e.color _ v.type.ports[portIndex].color; portIndex _ portIndex + 1; ENDLOOP; IF portIndex # v.type.ports.length THEN ERROR; }; ENDCASE => ERROR; v.oldColor _ v.curColor; EnQ[v]}; hts: CARDINAL _ MAX[MinHashSize, Real.RoundC[sizeFactor * (a.parts.Size[] + b.parts.Size[] + 2)]]; curGraph: RealGraphID; QFirst _ endOfQ; QCount _ 0; oldColorTable _ curColorTable _ IntHashTable.Create[hts, colorClass]; curGraph _ A; [] _ a.parts.Pairs[InitVertex]; [] _ InitVertex[a.mirror]; --AM1 curGraph _ B; [] _ b.parts.Pairs[InitVertex]; [] _ InitVertex[b.mirror]; nonUniqueCount[A] _ a.parts.Size[] + 1; nonUniqueCount[B] _ b.parts.Size[] + 1; IF QCount # (nonUniqueCount[A] + nonUniqueCount[B]) THEN ERROR; }; SetQToAllNonUniques: PROC = { AddVertex: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { v: Vertex; stop _ FALSE; WITH ra SELECT FROM vtx: Vertex => v _ vtx; a: Alias => {v _ NARROW[AntiAlias[a]]; IF a.name # PickAName[v.names] THEN RETURN}; ENDCASE => ERROR; IF v.QNext # notInQ THEN ERROR; EnQ[v]}; wasAll _ TRUE; a.parts.EnumerateIncreasing[AddVertex]; [] _ AddVertex[a.mirror]; --AM1 b.parts.EnumerateIncreasing[AddVertex]; [] _ AddVertex[b.mirror]; IF QCount # (nonUniqueCount[A] + nonUniqueCount[B]) THEN ERROR; hashTable.firstNonEmpty _ NullIndex}; ChoosePairs: PROC [useSuspects: BOOL] RETURNS [pairCount: CARDINAL] = { wasAll _ TRUE; pairCount _ 0; FOR hti: HashTableIndex _ hashTable.firstNonEmpty, hashTable[hti].nextNonEmpty WHILE hti # NullIndex DO first: ARRAY RealGraphID OF Vertex _ [NIL, NIL]; IF hashTable[hti].suspect # useSuspects THEN LOOP; FOR v: Vertex _ hashTable[hti].v, v.colorNext WHILE v # NIL DO IF v.QNext # notInQ THEN ERROR; IF first[v.graph] = NIL THEN first[v.graph] _ v; ENDLOOP; IF first[A]#NIL AND first[B]#NIL THEN { IF first[A].unique # first[B].unique THEN ERROR; IF NOT first[A].unique THEN { IF first[A].QNext # notInQ THEN ERROR; IF first[B].QNext # notInQ THEN ERROR; pairCount _ pairCount + 1; EnQ[first[A]]; EnQ[first[B]]}}; ENDLOOP; hashTable.firstNonEmpty _ NullIndex}; nonUniqueCount: TwoCount _ ALL[LAST[CARDINAL]]; curColorData, oldColorData: ColorTable _ NIL; pass: CARDINAL _ 0; QFirst: Vertex; QCount: CARDINAL; wasAll: BOOL _ TRUE; Initialize[]; WriteAll["CompareCDs Initialized", a, b, curColorData]; WHILE nonUniqueCount[A]#0 AND nonUniqueCount[B]#0 DO mcCount: CARDINAL _ 0; someMC: BOOL _ FALSE; pass _ pass + 1; WHILE QFirst # endOfQ DO v: Vertex _ QFirst; oldColor: Color _ v.oldColor; newColor: Color _ v.curColor _ ComputeColor[v]; ncd: ColorData = GetColorData[curColorData, newColor]; IF QFirst = notInQ THEN ERROR; QFirst _ v.QNext; v.QNext _ notInQ; IF wasAll AND NOT someMC THEN { ocd: ColorData = NARROW[oldColorData.Fetch[oldColor]]; IF ocd.newColor = noColor THEN ocd.newColor _ newColor ELSE IF ocd.multicolored THEN ERROR ELSE IF ocd.newColor = newColor THEN NULL ELSE ocd.multicolored _ someMC _ TRUE; }; v.colorNext _ ncd.firstVertex; ncd.firstVertex _ v; ncd.count[v.graph] _ ncd.count[v.graph] + 1; ENDLOOP; QCount _ 0; FOR hti: HashTableIndex _ hashTable.firstNonEmpty, hashTable[hti].nextNonEmpty WHILE hti # NullIndex DO uniques: ARRAY RealGraphID OF BOOL = [hashTable[hti].count[A]=1, hashTable[hti].count[B]=1]; unique: BOOL _ uniques[A] AND uniques[B]; IF unique THEN { a: Vertex _ hashTable[hti].v; b: Vertex _ a.colorNext; IF b.colorNext # NIL THEN ERROR; IF a.graph = b.graph THEN ERROR; IF a.unique OR b.unique THEN ERROR; a.unique _ b.unique _ TRUE; a.equiv _ b; b.equiv _ a; nonUniqueCount[A] _ nonUniqueCount[A] - 1; nonUniqueCount[B] _ nonUniqueCount[B] - 1; }; ENDLOOP; FOR hti: HashTableIndex _ hashTable.firstNonEmpty, hashTable[hti].nextNonEmpty WHILE hti # NullIndex DO uniques: ARRAY RealGraphID OF BOOL = [hashTable[hti].count[A]=1, hashTable[hti].count[B]=1]; unique: BOOL _ uniques[A] AND uniques[B]; IF unique THEN { a: Vertex _ hashTable[hti].v; b: Vertex _ a.colorNext; IF b.colorNext # NIL THEN ERROR; IF a.graph = b.graph THEN ERROR; IF NOT (a.unique AND b.unique) THEN ERROR; AddFrontier[a]; AddFrontier[b]; }; hashTable[hti].suspect_ hashTable[hti].count[A] # hashTable[hti].count[B]; FOR v: Vertex _ hashTable[hti].v, v.colorNext WHILE v # NIL DO v.oldColor _ v.curColor; v.suspect _ hashTable[hti].suspect; ENDLOOP; hashTable[hti].count[A] _ 0; hashTable[hti].count[B] _ 0; hashTable[hti].newColor _ noColor; hashTable[hti].multicolored _ FALSE; ENDLOOP; WriteAll[IO.PutFR["Almost end of pass %g", IO.card[pass]], a, b, hashTable]; Log["QCount=%g, nonUniqueCount=[%g, %g], someMC=%g, wasAll=%g\n", IO.card[QCount], IO.card[nonUniqueCount[A]], IO.card[nonUniqueCount[B]], IO.bool[someMC], IO.bool[wasAll]]; WriteQ[QFirst]; IF QCount > 0 THEN { wasAll _ (nonUniqueCount[A] + nonUniqueCount[B]) = QCount; hashTable.firstNonEmpty _ NullIndex} ELSE IF someMC OR (NOT wasAll) THEN SetQToAllNonUniques[] ELSE {pairCount: CARDINAL _ ChoosePairs[useSuspects: FALSE]; IF pairCount = 0 THEN {QFirst _ endOfQ; QCount _ 0; pairCount _ ChoosePairs[useSuspects: TRUE]; IF pairCount = 0 THEN EXIT}}; ENDLOOP; equiv _ nonUniqueCount[A]=0 AND nonUniqueCount[B]=0; END; HashRope: PROC [r: ROPE, hashTableSize: CARDINAL] RETURNS [c: Color] = BEGIN len: INT = r.Length[]; c _ 1; FOR i: INT DECREASING IN [0 .. len) DO char: CHAR _ r.Fetch[i]; long: LONG CARDINAL _ rot*c + (char-0C); c _ long MOD hashTableSize; ENDLOOP; END; rot: LONG CARDINAL _ 128 + 32 + 2; CTEquivClass: PROC [ct: CellType] RETURNS [equivClass: EquivClass] = { equivClass _ IF ct.equivClass = implicitClass THEN PickAName[ct.names] ELSE ct.equivClass}; PortEquivClass: PROC [ct: CellType, pi: PortIndex] RETURNS [equivClass: EquivClass] = { equivClass _ IF ct.ports[pi].equivClass = implicitClass THEN PickAName[ct.ports[pi].names] ELSE ct.ports[pi].equivClass}; WriteQ: PROC [QFirst: Vertex] = BEGIN first: BOOL _ TRUE; Log["Q = {"]; FOR QFirst _ QFirst, QFirst.QNext WHILE QFirst # endOfQ DO IF QFirst = notInQ THEN ERROR; IF first THEN first _ FALSE ELSE Log[", "]; Log["%g.%g", IO.rope[graphIDToRope[QFirst.graph]], IO.rope[PickAName[QFirst.names]]]; ENDLOOP; Log["}\n"]; END; Test: PROC [da, db: Design, aName, bName: ROPE] = BEGIN aType: CellType _ NARROW[Lookup[da.cellTypesByName, aName]]; bType: CellType _ NARROW[Lookup[db.cellTypesByName, bName]]; equiv: BOOL; EnsureParts[aType]; EnsureParts[bType]; Log["\nTesting %g %g\n", IO.rope[aName], IO.rope[bName]]; equiv _ CompareGraphs[aType, bType, FALSE]; Log["\nEquiv = %g.\n", IO.bool[equiv]]; FlushLog[]; END; END. TLichenCompare.Mesa Last Edited by: Spreitzer, February 5, 1986 5:36:20 pm PST Κ '– "cedar" style˜Icode™J™:K˜KšΟk œ!œ ˜9K˜šΠbx œœ˜Kšœ œ ˜!Kšœ!˜(K˜Kšœœ ˜*K˜Kš œ œœ œœ˜/K˜Kš œœœ œœœœ#˜[K˜Kšœœ œ ˜(K˜Kšœ œ˜Kšœ œ˜K˜K˜š Οn œœœ$œ œ˜UKš˜šŸ œœ œ˜9Kšœ˜šœ.œœ˜AK˜,Kšœœœ˜%Kšœœ œ/˜EKšœ˜ ——Kš Ÿœœœœ œœ6˜|šŸ œœ˜!šœ.œœ˜AKšœœœ˜%K˜$Kšœ˜ ——šŸ œœ˜šŸ œœœœœœœΟcœ˜gKšœ ˜ šœœ˜Kšœ˜Kšœœ˜—K˜Kšœ œœœ˜+Kšœ œ˜Kšœ œ˜šœ ˜K˜$˜ K˜K˜šœ+œœ˜>Kšœœœ˜"K˜(K˜Kšœ˜—Kšœ!œœ˜.K˜—Kšœœ˜—K˜K˜—KšœœœO˜bK˜K˜K˜EKšœ œ˜ Kšœ; ˜@Kšœ œ˜ Kšœ:˜:Kšœœ˜'Kšœœ˜'Kš œœœœœ˜?Kšœ˜—šŸœœ˜š Ÿ œœœœœœ˜6Kšœ ˜ Kšœœ˜ šœœ˜K˜Kš œœœœœ˜SKšœœ˜—Kšœœœ˜Kšœ˜—Kšœ œ˜KšœB ˜GKšœA˜AKš œœœœœ˜?Kšœ%˜%—š Ÿ œœœœ œ˜GKšœ œ˜šœLœ˜gKš œœ œ œœ˜0Kšœ&œœ˜2šœ+œœ˜>Kšœœœ˜Kšœœœ˜0Kšœ˜—šœœœœœœœ˜'Kš œœœ œœ˜0šœœœ œ˜Kšœœœœ˜&Kšœœœœ˜&Kšœ˜Kšœ œœ˜——Kšœ˜—Kšœ%˜%—Kšœœœœ˜/Kšœ)œ˜-Kšœœ˜K˜Kšœœ˜Kšœœœ˜K˜ Kšœ7˜7š œœœœ˜4Kšœ œ˜Kšœœœ˜Kšœ˜šœ˜K˜K˜Kšœ/˜/Kšœ6˜6Kšœœœ˜K˜Kšœ˜šœœœœ˜Kšœœ˜6Kšœœ˜6Kšœœœ˜#Kšœœœ˜)Kšœœ˜&K˜—Kšœ˜Kšœ˜Kšœ,˜,Kšœ˜—K˜ šœLœ˜gKš œ œ œœœœ˜\Kš œœ œœ œ˜)šœœ˜Kšœ˜K˜Kšœœœœ˜ Kšœœœ˜ Kšœ œ œœ˜#Kšœœ˜K˜Kšœœœ˜*Kšœœœ˜*K˜—Kšœ˜—šœLœ˜gKš œ œ œœœœ˜\Kš œœ œœ œ˜)šœœ˜Kšœ˜K˜Kšœœœœ˜ Kšœœœ˜ Kš œœ œ œœ˜*Kšœ˜K˜—Kšœ-œœ˜Jšœ+œœ˜>K˜Kšœ#˜#Kšœ˜—Kšœœ˜Kšœœ˜Kšœ"˜"Kšœœ˜$Kšœ˜—Kšœ œ œ˜LšœA˜AKšœœœ˜,Kšœœœœ˜>—K˜šœ œ˜Kšœœœ ˜:K˜$—Kš œœœœ œ˜9šœ œœ˜<šœœ˜3Kšœ%œ˜+Kšœœœ˜——Kšœ˜—Kšœœœœ˜4Kšœ˜—K˜š Ÿœœœœœ ˜FKš˜Kšœœ˜K˜š œœ œœ ˜&Kšœœ˜Kšœœœ˜(Kšœ œ˜Kšœ˜—Kšœ˜Kšœœœ˜"—K˜šŸ œœœ˜FKšœ œœœ˜[—K˜šŸœœœ˜WKšœ œ)œœ˜y—K˜šŸœœ˜Kš˜Kšœœœ˜K˜ šœœ˜:Kšœœœ˜Kšœœ œœ ˜+Kšœ œ$œ ˜UKšœ˜—K˜ Kšœ˜—K˜šŸœœ œ˜1Kš˜Kšœœ$˜