<> <> <> <> <> <> DIRECTORY Basics USING [CompareCard, Comparison], BasicTime USING [GMT, Now, Period], CD USING [Object, Orientation, Transformation], CDBasics USING [DecomposeOrient], CDOps USING [ToRope], Checksum USING [ComputeChecksum], Core USING [Wire], DrcDebug USING [debug, dLog, PrintWire], IO, -- debugging only PrincOpsUtils USING [], RefTab USING [Create, Delete, EachPairAction, Erase, Fetch, GetSize, Insert, Key, Pairs, Store, Ref, Val], Rope USING [ROPE], TNT USING []; TNTImpl: CEDAR PROGRAM IMPORTS Basics, BasicTime, CDBasics, CDOps, Checksum, DrcDebug, RefTab, IO EXPORTS TNT ~ BEGIN <> TNT: PUBLIC TYPE ~ REF TNTRep; -- The Neighbourhood Ref TNTRep: PUBLIC TYPE ~ RECORD [table: RefTab.Ref, lastSweep: BasicTime.GMT]; TNTkey: TYPE ~ REF TNTkeyRep; TNTkeyRep: TYPE ~ RECORD [cell1, cell2: CD.Object, relPos: CD.Transformation]; <> TNTdata: TYPE ~ REF TNTdataRep; TNTdataRep: TYPE ~ RECORD [neverAccessed: BOOL _ TRUE, actual1, actual2: Core.Wire]; TNTrecord: TYPE ~ RECORD [k: TNTkey, d: TNTdata]; TNTsize: NAT ~ 31991; -- 10007, 21383, 22307 TNThighWaterMark: NAT = (TNTsize / 3) * 2; -- optimization sweepInterval: INT ~ 25200; -- in seconds Hash: PROC [k: RefTab.Key] RETURNS [CARDINAL] ~ BEGIN <> TRUSTED {RETURN [Checksum.ComputeChecksum [0, SIZE [TNTkeyRep], LOOPHOLE [k]]]} END; -- Hash Match: PROC [key1, key2: RefTab.Key] RETURNS [BOOL] ~ BEGIN <> k1: TNTkey ~ NARROW [key1, TNTkey]; k2: TNTkey = NARROW [key2, TNTkey]; RETURN [(k1^ = k2^)] END; -- Match InitTNT: PUBLIC PROC RETURNS [t: TNT] ~ BEGIN <> t _ NEW [TNTRep _ [table: RefTab.Create [TNTsize, Match, Hash], lastSweep: BasicTime.Now []]]; END; -- InitTNT BlowTNT: PUBLIC PROC [t: TNT] ~ BEGIN <> t.table.Erase; t _ NIL END; -- BlowTNT BuildTNTrecord: PROC [o1, o2: CD.Object, t1, t2: CD.Transformation, a1, a2: Core.Wire] RETURNS [rec: TNTrecord] ~ BEGIN <> order: Basics.Comparison; rec.k _ NEW [TNTkeyRep]; rec.d _ NEW [TNTdataRep]; TRUSTED {order _ Basics.CompareCard [LOOPHOLE[o1], LOOPHOLE[o2]]}; IF order = greater THEN BEGIN oZ: CD.Object = o1; tZ: CD.Transformation = t1; aZ: Core.Wire = a1; o1 _ o2; o2 _ oZ; t1 _ t2; t2 _ tZ; a1 _ a2; a2 _ aZ END; rec.k.cell1 _ o1; rec.k.cell2 _ o2; rec.k.relPos _ [[t2.off.x - t1.off.x, t2.off.y - t1.off.y], CDBasics.DecomposeOrient [t1.orient, t2.orient]]; rec.d.actual1 _ a1; rec.d.actual2 _ a2 END; -- BuildTNTrecord RememberTNT: PUBLIC PROC [t: TNT, o1, o2: CD.Object, t1, t2: CD.Transformation, a1, a2: Core.Wire] ~ BEGIN <> rec: TNTrecord ~ BuildTNTrecord [o1, o2, t1, t2, a1, a2]; [] _ t.table.Insert [rec.k, rec.d] END; -- Remember InTNT: PUBLIC PROC [t: TNT, o1, o2: CD.Object, t1, t2: CD.Transformation, a1, a2: Core.Wire] RETURNS [BOOL] ~ BEGIN <> rec: TNTrecord ~ BuildTNTrecord [o1, o2, t1, t2, a1, a2]; isThere: BOOL; rawData: RefTab.Val; data: TNTdata; SameSignals: PROC RETURNS [BOOL] ~ INLINE BEGIN IF (data.actual1.size # rec.d.actual1.size) OR (data.actual2.size # rec.d.actual2.size) THEN RETURN [FALSE]; FOR i: NAT IN [0 .. rec.d.actual1.size) DO IF (rec.d.actual1[i] # data.actual1[i]) THEN RETURN [FALSE] ENDLOOP; FOR i: NAT IN [0 .. rec.d.actual2.size) DO IF (rec.d.actual2[i] # data.actual2[i]) THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE] END; -- SameSignals [found: isThere, val: rawData] _ t.table.Fetch [rec.k]; data _ NARROW [rawData, TNTdata]; IF DrcDebug.debug AND isThere AND NOT SameSignals [] THEN BEGIN DrcDebug.dLog.Put1 [IO.rope ["Same key, but different signals:\n"]]; [] _ PrintEltLong [rec.k, rec.d]; [] _ PrintEltLong [rec.k, data] END; isThere _ isThere AND SameSignals []; IF isThere THEN data.neverAccessed _ FALSE; RETURN [isThere] END; -- InTNT UpdateTNT: PUBLIC PROC [t: TNT, o1, o2: CD.Object, t1, t2: CD.Transformation, a1, a2: Core.Wire] RETURNS [wasThere: BOOL] ~ BEGIN <> rec: TNTrecord ~ BuildTNTrecord [o1, o2, t1, t2, a1, a2]; rawData: RefTab.Val; data: TNTdata; SameSignals: PROC RETURNS [BOOL] ~ INLINE BEGIN IF (data.actual1.size # rec.d.actual1.size) OR (data.actual2.size # rec.d.actual2.size) THEN RETURN [FALSE]; FOR i: NAT IN [0 .. rec.d.actual1.size) DO IF (rec.d.actual1[i] # data.actual1[i]) THEN RETURN [FALSE] ENDLOOP; FOR i: NAT IN [0 .. rec.d.actual2.size) DO IF (rec.d.actual2[i] # data.actual2[i]) THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE] END; -- SameSignals [found: wasThere, val: rawData] _ t.table.Fetch [rec.k]; data _ NARROW [rawData, TNTdata]; wasThere _ wasThere AND SameSignals []; IF wasThere THEN data.neverAccessed _ FALSE ELSE [] _ t.table.Store [rec.k, rec.d] END; -- UpdateTNT SweepTNT: PUBLIC PROC [t: TNT] ~ BEGIN <> RemoveCadavers: RefTab.EachPairAction ~ BEGIN <> IF NARROW [val, TNTdata].neverAccessed THEN [] _ t.table.Delete [key] END; -- RemoveCadavers IF (BasicTime.Period[t.lastSweep,BasicTime.Now[]] > sweepInterval) AND (t.table.GetSize > TNThighWaterMark) THEN {[] _ t.table.Pairs [RemoveCadavers]; t.lastSweep _ BasicTime.Now []} END; -- SweepTNT <> rot: ARRAY CD.Orientation OF Rope.ROPE ~ [original: "0", mirrorX: "x", rotate90: "90", rotate90X: "90x", rotate180: "180", rotate180X: "180x", rotate270: "-90", rotate270X: "-90x"]; PrintEltShort: RefTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOLEAN _ FALSE]>> k: TNTkey ~ NARROW [key, TNTkey]; data: TNTdata ~ NARROW [val, TNTdata]; DrcDebug.dLog.PutF ["Key: %g, %g; %g, (%g, %g).\n", IO.card[LOOPHOLE[k.cell1]], IO.card[LOOPHOLE[k.cell2]], IO.rope[rot[k.relPos.orient]], IO.int[k.relPos.off.x], IO.int[k.relPos.off.y]]; FOR i: NAT IN [0 .. data.actual1.size) DO DrcDebug.dLog.Put [IO.card[LOOPHOLE[data.actual1[i]]], IO.char[' ]] ENDLOOP; DrcDebug.dLog.Put1 [IO.char['\n]]; FOR i: NAT IN [0 .. data.actual2.size) DO DrcDebug.dLog.Put [IO.card[LOOPHOLE[data.actual2[i]]], IO.char[' ]] ENDLOOP; DrcDebug.dLog.Put1 [IO.char['\n]] END; -- PrintEltShort PrintEltLong: RefTab.EachPairAction ~ BEGIN <<[key: Key, val: Val] RETURNS [quit: BOOLEAN _ FALSE]>> k: TNTkey = NARROW [key, TNTkey]; data: TNTdata = NARROW [val, TNTdata]; DrcDebug.dLog.PutF ["Key: %g, %g; %g, (%g, %g) ", IO.card[LOOPHOLE[k.cell1]], IO.card[LOOPHOLE[k.cell2]], IO.rope[rot[k.relPos.orient]], IO.int[k.relPos.off.x], IO.int[k.relPos.off.y]]; DrcDebug.dLog.PutF ["[CD objects: <%g>, <%g>].\n", IO.rope[CDOps.ToRope[k.cell1]], IO.rope[CDOps.ToRope[k.cell2]]]; DrcDebug.PrintWire [data.actual1]; DrcDebug.PrintWire [data.actual2]; DrcDebug.dLog.Put1 [IO.char['\n]] END; -- PrintEltLong PrintTNTLong: PROC [t: TNT] ~ BEGIN <> DrcDebug.dLog.PutRope ["\nNeighbourhood Ref:\n"]; [] _ RefTab.Pairs [t.table, PrintEltLong] END; -- PrintTNT END.