SXShowRulesImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Giordano Beretta, May 7, 1985 11:11:40 am PDT
gbb March 25, 1986 2:29:47 pm PST
DIRECTORY
Atom USING [GetPName],
CD USING [Design, Layer, LayerKey, Number, Technology],
CDMenus USING [CreateEntry],
CDProperties USING [GetProp],
CDSequencer USING [Command, ImplementCommand],
IO USING [atom, char, int, Put, PutF, rope, RopeFromROS, ROS, STREAM],
Rope USING [Cat, FromRefText, ROPE],
SXAtoms USING [spinifex],
SX USING [BoxMapProc, Constraint, ConstraintArray, ConstraintIndex, excludeIndex, GeometricRule, MapRec, maxConstraints, nodeIndex, spaceIndex, SpinifexLayerIndex, techCIndexBase, TechHandle, violateIndex],
TerminalIO USING [WriteRope];
SXShowRulesImpl: CEDAR PROGRAM
IMPORTS Atom, CD, CDMenus, CDProperties, CDSequencer, IO, Rope, SXAtoms, TerminalIO =
BEGIN
TriggerMap: TYPE = PACKED ARRAY SX.ConstraintIndex OF BOOLEAN;
Write: PROCEDURE [data: REF] =
Writes the data (a rope or a stream) to the output.
BEGIN
WITH data SELECT FROM
rope: Rope.ROPE => TerminalIO.WriteRope [rope];
stream: IO.STREAM => TerminalIO.WriteRope [IO.RopeFromROS[stream]];
text: REF TEXT => TerminalIO.WriteRope [Rope.FromRefText[text]];
ENDCASE => ERROR;
END; -- Write
RegisterCommand: PROCEDURE ~ {
id: ATOM ~ $showRules;
CDSequencer.ImplementCommand [key: id, proc: WriteTechHandle, queue: doQueue];
CDMenus.CreateEntry [menu: $ProgramMenu, entry: "Show Spinifex Rules", key: id];
TerminalIO.WriteRope ["Spinifex utility showing design rules loaded.\n"]
}; -- end RegisterCommand
WriteTechHandle: PROCEDURE [comm: CDSequencer.Command] ~ {
design: CD.Design ~ comm.design;
technologyHandle: REF SX.TechHandle;
technologyHandle ← NARROW [CDProperties.GetProp [from: design.technology, prop: SXAtoms.spinifex]];
IF (technologyHandle = NIL) THEN {
TerminalIO.WriteRope ["The input focus is not on a design with a Spinifex technology.\n"];
ERROR ABORTED
};
Write [Rope.Cat ["\n***** The technology of the design ", design.name, " is ", design.technology.name, ".\n"]];
WriteLayers [th: technologyHandle];
WriteRules [th: technologyHandle, lambda: design.technology.lambda];
WriteConstraints [design: design, th: technologyHandle];
WriteConstraintResolution [th: technologyHandle];
Write ["Done\n"]
}; -- end WriteTechHandle
WriteLayers: PROCEDURE [th: REF SX.TechHandle] ~ {
info: IO.STREAM ~ IO.ROS [];
IO.PutF [stream: info, format: "It uses %g Spinifex layers.\nLayer number and name, Thyme name, and bloat factor:\n", v1: IO.int[th.numSpinifexLayers]];
FOR layer: SX.SpinifexLayerIndex IN [0.. th.numSpinifexLayers) DO
IO.PutF [stream: info,
format: "%3g %-15g %-5g %5g \n",
v1: IO.int[layer],
v2: IO.atom[th.spinifexLayerNames[layer].layerId],
v3: IO.rope[th.spinifexLayerNames[layer].thymeName],
v4: IO.int[th.layerInterestBloat[layer]]]
ENDLOOP;
Write [info]
}; -- end WriteLayers
WriteRules: PROCEDURE [th: REF SX.TechHandle, lambda: CD.Number] =
Writes the list of geometric rules for each layer.
BEGIN
Write ["\n***** Design rules:\n[So how does checking work? The four quads around a corner are mapped through trigger1 to TRUE/FALSE value for each quadrant. The TRUE area represents 'stuff' and if it forms a convex or concave corner a check is made of size extent into the corresponding 'non-stuff' in the FALSE region. To do a width check we map space to TRUE and the material being width checked to FALSE, thus an appropriate check is generated extending into the material. The check fails if anything in the check region maps through trigger2 to TRUE. If okIfConnected is TRUE then the violation is overidden if trigger1 and trigger2 circuit nodes and are the same. The trigger tables must be hand generated by the tech dependent client and are therefore error prone.]\n"];
FOR layer: SX.SpinifexLayerIndex IN [0.. th.numSpinifexLayers) DO
Write [Rope.Cat["List of rules for layer ", Atom.GetPName[th.spinifexLayerNames[layer].layerId], ":\n"]];
IF th.rules[layer] = NIL THEN Write ["none"];
FOR rules: LIST OF REF SX.GeometricRule ← th.rules[layer], rules.rest WHILE rules # NIL DO
info: IO.STREAM ~ IO.ROS [];
IO.PutF [stream: info,
format: "%g; %3g  extent. May %gbe connected.\n",
v1: IO.rope[rules.first.message],
v2: IO.int[rules.first.extent / lambda],
v3: IO.rope[IF rules.first.okIfConnected THEN "" ELSE "not "]];
Write [info];
WriteTriggers [trigger1: rules.first.trigger1, trigger2: rules.first.trigger2, constraints: th.constraintResolutions[layer]^[0]]
ENDLOOP;
Write ["\n"];
ENDLOOP;
END; -- WriteRules
WriteTriggers: PROCEDURE [trigger1, trigger2: TriggerMap, constraints: SX.ConstraintArray] =
Called in "WriteRules". Tries to tell the consequences of the rules.
BEGIN
SpecificConstraints: TYPE = [SX.techCIndexBase .. SX.maxConstraints) ← SpecificConstraints.FIRST;
BEGIN-- trigger 1
info: IO.STREAM ~ IO.ROS [];
info.Put [IO.rope[" Trigger 1: "]];
FOR i: SX.ConstraintIndex IN SX.ConstraintIndex DO
IO.PutF [stream: info,
format: "%2g",
v1: IO.char[IF trigger1[i] THEN 'T ELSE 'F]];
ENDLOOP;
info.Put [IO.rope["\n"]];
IF trigger1[SX.nodeIndex] THEN
info.Put [IO.rope[" Will DRC areas for node regions.\n"]];
IF trigger1[SX.spaceIndex] THEN
info.Put [IO.rope[" Will DRC areas for space regions if there are no tiles in the CIF quad tree.\n"]];
IF trigger1[SX.excludeIndex] THEN
info.Put [IO.rope[" Will DRC areas for regions excluded by opaque cells.\n"]];
IF trigger1[SX.violateIndex] THEN
info.Put [IO.rope[" Will DRC areas for opaque cell exclusion region violations.\n"]];
FOR i: SpecificConstraints IN SpecificConstraints DO
IF trigger1[i] THEN
BEGIN
IF constraints[i] = NIL THEN IO.PutF [stream: info,
format: " ***** CONSTRAINT %g NOT INITIALIZED *****\n",
v1: IO.int[i]]
ELSE IO.PutF [stream: info,
format: " Will DRC area for constraint %g.\n",
v1: IO.atom[constraints[i].name]]
END;
ENDLOOP;
Write [info]
END; -- trigger 1
BEGIN-- trigger 2
info: IO.STREAM ~ IO.ROS [];
info.Put [IO.rope[" Trigger 2: "]];
FOR i: SX.ConstraintIndex IN SX.ConstraintIndex DO
IO.PutF [stream: info,
format: "%2g",
v1: IO.char[IF trigger2[i] THEN 'T ELSE 'F]];
ENDLOOP;
info.Put [IO.rope["\n"]];
IF trigger2[SX.nodeIndex] THEN
info.Put [IO.rope[" Rule is violated if there is a node.\n"]];
IF trigger2[SX.spaceIndex] THEN
info.Put [IO.rope[" Rule is violated if there are no tiles in the CIF quad tree.\n"]];
IF trigger2[SX.excludeIndex] THEN
info.Put [IO.rope[" Rule is violated if there is stuff in a region excluded by opaque cells.\n"]];
IF trigger2[SX.violateIndex] THEN
info.Put [IO.rope[" Rule is violated if there is a violation in a region excluded by opaque cells.\n"]];
FOR i: SpecificConstraints IN SpecificConstraints DO
IF trigger2[i] THEN
BEGIN
IF constraints[i] = NIL THEN IO.PutF [stream: info,
format: " ***** CONSTRAINT %g NOT INITIALIZED *****\n",
v1: IO.int[i]]
ELSE IO.PutF [stream: info,
format: " Rule is violated if there is constraint %g.\n",
v1: IO.atom[constraints[i].name]]
END;
ENDLOOP;
Write [info]
END-- trigger 2
END; -- WriteTriggers
WriteConstraints: PROCEDURE [design: CD.Design, th: REF SX.TechHandle] =
Writes the list of constraints for each layer.
BEGIN
Write ["\n***** Constraints\n[Note that the constraints are determined during the mapping from ChipNDale to Spinifex layers]:\n"];
FOR level: LIST OF CD.Layer ← design.technology.usedLayers, level.rest WHILE level # NIL DO
info: IO.STREAM ~ IO.ROS [];
layer: CD.Layer ← level.first;
IO.PutF [stream: info,
format: "List of constraints for ChipNDale layer %2g [%g]:\n",
v1: IO.int[layer],
v2: IO.atom[CD.LayerKey[layer]]];
Write [info];
IF th.cdLayerMapping[layer] = NIL THEN Write ["*** none ***"];
FOR map: LIST OF SX.MapRec ← th.cdLayerMapping[layer], map.rest WHILE map # NIL DO
info1: IO.STREAM ~ IO.ROS [];
IO.PutF [stream: info1,
format: "For Spinifex layer %g; bloat factor: %g;\n",
v1: IO.atom[th.spinifexLayerNames[map.first.spinifexLayer].layerId],
v2: IO.int[map.first.bloatFactor]];
WITH map.first.value SELECT FROM
c: REF SX.Constraint =>
BEGIN
IO.PutF [stream: info1, format: "The regions represent a constraint on other material in this layer.\nConstraint name: %g; index into the constraint array: %g.\n",
v1: IO.atom[c.name],
v2: IO.int[c.index]];
IF c.hasCorrespondingNode THEN IO.PutF [stream: info1, format: "Connectivity affects the rule and there is a corresponding layer which has the nodes associated with these regions.\n"];
IO.PutF [stream: info1,
format: "Node values are attached to constraints looking at layer %g.\n",
v1: IO.atom[th.spinifexLayerNames[c.correspondingNodeLayer].layerId]];
END;
p: REF SX.BoxMapProc => IO.PutF [stream: info1, format: "A procedural escape for more complex rectangle mapping is used for this ChipNDale layer.\n"];
ENDCASE => IO.PutF [stream: info1, format: "No constraint from this ChipNDale layer; the regions represent conductive material on this layer and a new Spinifex node is created.\n"];
IO.PutF [stream: info1, format: "\n"]; Write [info1];
ENDLOOP;
Write [".\n"];
ENDLOOP;
END; -- WriteConstraints
WriteConstraintResolution: PROCEDURE [th: REF SX.TechHandle] =
Writes the constraint resolution table for each Spinifex layer.
BEGIN
Write ["\n***** Constraint resolution tables:\n"];
FOR i: SX.SpinifexLayerIndex IN SX.SpinifexLayerIndex DO
IF th.constraintResolutions[i] # NIL THEN
BEGIN
info: IO.STREAM ~ IO.ROS [];
IO.PutF [stream: info,
format: "Constraint resolution table for Spinifex layer %g:\n",
v1: IO.atom[th.spinifexLayerNames[i].layerId]];
FOR j: SX.ConstraintIndex IN SX.ConstraintIndex DO
IO.PutF [stream: info, format: "constraint index %g: ", v1: IO.int[j]];
FOR k: SX.ConstraintIndex IN SX.ConstraintIndex DO
IF th.constraintResolutions[i][j][k] # NIL THEN
BEGIN
IO.PutF [stream: info,
format: "%g: %g[%g], ",
v1: IO.int[k],
v2: IO.atom[th.constraintResolutions[i][j][k].name],
v3: IO.int[th.constraintResolutions[i][j][k].index]];
END;
ENDLOOP;
IO.PutF [stream: info, format: "\n"];
ENDLOOP;
Write [info]; Write ["\n"]
END;
ENDLOOP;
END; -- WriteConstraintResolution
RegisterCommand []
END.