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] = 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] = 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] = 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] = 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] = 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. ÒSXShowRulesImpl.mesa Copyright c 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 Writes the data (a rope or a stream) to the output. Writes the list of geometric rules for each layer. Called in "WriteRules". Tries to tell the consequences of the rules. Writes the list of constraints for each layer. Writes the constraint resolution table for each Spinifex layer. Ê ˜™Jšœ Ïmœ1™šŸœž œžœ˜J™3Lšž˜šžœžœž˜Kšœ žœ ˜/Kšœžœžœžœ˜CKšœžœžœ2˜@Kšžœžœ˜—LšžœÏc˜ —šŸœž œ˜Kšœžœ˜LšœN˜NKšœP˜PKšœH˜HKšœ ˜—šŸœž œ ˜:Kšœžœ˜ Kšœžœ˜$LšœžœJ˜cšžœžœžœ˜"KšœZ˜ZKšžœž˜ K˜—Kšœo˜oKšœ#˜#KšœD˜DKšœ8˜8Kšœ1˜1K˜Kšœ Ïe˜—šŸ œž œžœ˜2Jš œžœžœžœžœ˜L•StartOfExpansion¯[stream: STREAM, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šžœ–˜˜šžœžœž˜AKš žœ:žœžœ1žœ3žœ#˜ÜKšž˜—Kšœ ˜ Kšœ ¡˜—šŸ œž œžœžœ ˜BJ™2Lšž˜K–[]šœ˜šžœžœžœž˜AKšœi˜iKšžœžœžœ˜-šžœžœžœžœžœ-žœ žœž˜ZKš œžœžœžœžœ˜Kšžœ'Ïgœ%žœ žœ'žœžœžœžœ ˜ÕKšœ ˜ Kšœ€˜€Kšžœ˜—Kšœ ˜ Kšžœ˜—Lšžœ  ˜—šŸ œž œ/žœ˜\JšœD™DLšž˜Kš œžœžœžœ'žœ˜ašžœ  ˜Kš œžœžœžœžœ˜Lšœ žœ˜%š žœžœžœžœž˜2Kš žœ(žœžœ žœžœ˜SKšžœ˜—Kšœ žœ ˜šžœ žœ ž˜Kšœ žœ2˜>—šžœ žœ ž˜Kšœ žœ^˜j—šžœ žœž˜!Kšœ žœF˜R—šžœ žœž˜!Kšœ žœM˜Y—šžœžœž˜4šžœ ž˜Kšž˜Kš žœžœžœžœSžœ˜|KšžœžœLžœ˜pKšžœ˜—Kšžœ˜—Kšœ ˜ Kšžœ  ˜—šžœ  ˜Kš œžœžœžœžœ˜Kšœ žœ˜%š žœžœžœžœž˜2Kš žœ(žœžœ žœžœ˜SKšžœ˜—Kšœ žœ ˜šžœ žœ ž˜Kšœ žœ6˜B—šžœ žœ ž˜Kšœ žœN˜Z—šžœ žœž˜!Kšœ žœZ˜f—šžœ žœž˜!Kšœ žœ`˜l—šžœžœž˜4šžœ ž˜Kšž˜Kš žœžœžœžœSžœ˜|KšžœžœWžœ˜{Kšžœ˜—Kšžœ˜—Kšœ ˜ Kšžœ  ˜—Lšžœ ˜—š Ÿœž œ žœ žœžœ˜HJšœ.™.Lšž˜K–[]šœ‚˜‚š žœžœžœžœ2žœ žœž˜[Kš œžœžœžœžœ˜Kšœžœ˜KšžœXžœžœžœ˜ŠKšœ ˜ Kšžœžœžœ˜>š žœžœžœ0žœžœž˜RKš œžœžœžœžœ˜KšžœPžœCžœ˜¶šžœžœž˜ šœžœ˜Jšž˜Kšžœ¦žœžœ˜ÎKšžœžœžœ—˜¸Kšžœdžœ@˜¨Kšžœ˜—Kšœžœžœ|˜–Kšžœžœ¨˜µ—Kšžœ3˜5Kšžœ˜—Kšœ˜Kšžœ˜—Lšžœ ¡˜—šŸœž œžœ˜>J™?Lšž˜Kšœ2˜2šžœžœž˜8šžœžœž˜)Kšž˜Kš œžœžœžœžœ˜KšžœYžœ*˜‡šžœžœž˜2Kšžœ:žœ ˜Gšžœžœž˜2šžœ%žœž˜/Kšž˜Kšžœ1žœ žœ3žœ/˜¨Kšžœ˜—Jšžœ˜—Jšžœ#˜%Kšžœ˜—Kšœ˜Kšžœ˜—Kšžœ˜—Lšžœ ˜!—Lšœ˜Lšžœ˜—…—%l1E