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.