DIRECTORY Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDPanelFonts, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, Core, CoreClasses, CoreOps, CoreGeometry, CoreProperties, GList, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerClasses, ViewerOps; SisyphCmdsImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDOps, CDPanelFonts, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, CoreClasses, CoreOps, CoreGeometry, CoreProperties, GList, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerOps SHARES CDPopUpMenus, Sisyph = BEGIN ROPE: TYPE = Rope.ROPE; ROPES: TYPE = LIST OF ROPE; Wire: TYPE = Core.Wire; Wires: TYPE = Core.Wires; CellType: TYPE = Core.CellType; Icon: TYPE ~ REF IconRep; IconRep: TYPE ~ RECORD [ name: ROPE _ NIL, -- The short name of the icon, i.e. excluding the ".icon" part boxWidth: CD.Number, -- Width of lines for icon box pinRect: CD.Position, -- Size of pins (horizontal pin) guard: CD.Number, -- Spacing between pin and pin name grid: CD.Number, -- The grid on which pins should be aligned font: CDTexts.CDFont, -- ChipNDale font to be used for all texts pins: ARRAY CoreGeometry.Side OF ROPES -- The sorted pin names on all four sides ]; UnMakeIcon: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeCellIconWithCodeDef: PROC [comm: CDSequencer.Command] = { iconName: ROPE; selected: CD.Instance; multiple: BOOL; cellIconExprPrefix: ROPE _ Rope.Cat[Sisyph.cellIconRope, " _ "]; cellIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; iconName _ CDDirectory.Name[selected.ob]; IF NOT Rope.Match["*.icon", iconName] THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"]; cellIconExpr _ TerminalIO.RequestRope[Rope.Cat["Type code: ", cellIconExprPrefix]]; cellIconExpr _ Rope.Cat[cellIconExprPrefix, cellIconExpr]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [cellIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeCellIconWithGeometryDef: PROC [comm: CDSequencer.Command] = { iconName: ROPE; selected: CD.Instance; multiple: BOOL; schematicName: ROPE; cellIconExprPrefix: ROPE _ Rope.Cat[Sisyph.cellIconRope, " _ "]; cellIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; iconName _ CDDirectory.Name[selected.ob]; IF NOT Rope.Match["*.icon", iconName] THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"]; schematicName _ TerminalIO.RequestRope["Type schematic name: "]; IF CDDirectory.Fetch[comm.design, schematicName].object = NIL THEN { TerminalIO.PutF["*** No such object in design.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"]; cellIconExpr _ Rope.Cat[cellIconExprPrefix, "ES[\"", schematicName, "\", cx]"]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [cellIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, schematicName]; }; MakeWireIconWithCodeDef: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; wireIconExprPrefix: ROPE _ Rope.Cat[Sisyph.wireIconRope, " _ "]; wireIconExpr: ROPE; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; wireIconExpr _ TerminalIO.RequestRope[Rope.Cat["Type code: ", wireIconExprPrefix]]; wireIconExpr _ Rope.Cat[wireIconExprPrefix, wireIconExpr]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [wireIconExpr, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; CreateIconCommand: PROC [comm: CDSequencer.Command] ~ { schematicName, iconShortName: ROPE; icon: CD.Object; cell: Core.CellType; selected: CD.Instance; multiple: BOOL; grid: CD.Number _ -1; cellRef: REF; viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF viewer#NIL THEN WITH ViewerOps.GetViewer[viewer, $Grid] SELECT FROM rgrid: REF CD.Number => grid _ rgrid^; ENDCASE => NULL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; schematicName _ CDDirectory.Name[selected.ob]; IF schematicName=NIL THEN { TerminalIO.PutF["*** Selected schematic has no name.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"]; cellRef _ SinixOps.ExtractCDInstance[selected, comm.design, Sisyph.mode].result; IF ISTYPE [cellRef, Core.CellType] THEN cell _ NARROW [cellRef] ELSE { TerminalIO.PutF["*** Selected cell does not extract to Core CellType\n"]; RETURN; }; iconShortName _ TerminalIO.RequestRope["Type icon short name: "]; IF Rope.IsEmpty[iconShortName] THEN iconShortName _ IF Rope.Match["*.sch", schematicName] THEN Rope.Substr[schematicName, 0, Rope.Length[schematicName]-4] ELSE schematicName; IF Rope.IsEmpty[schematicName] THEN { TerminalIO.PutF["No name provided, no default from schematic.\n"]; RETURN; }; IF CDDirectory.Fetch[comm.design, Rope.Cat[iconShortName, ".icon"]].found THEN { TerminalIO.PutF["*** The icon %g.icon already exists!\n", IO.rope[iconShortName]]; RETURN; }; icon _ IconFromSchematic[cell, schematicName, iconShortName, comm.design, grid]; IF icon=NIL THEN RETURN; CDCells.SetSimplificationTreshhold[cell: icon, val: 30, inPixels: TRUE]; CDOps.IncludeObjectI[comm.design, icon, comm.pos]; }; MakeSequenceIcon: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; IF NOT CDCells.IsCell[selected.ob] THEN { TerminalIO.PutF["*** Selected object is not a cell.\n"]; RETURN; }; IF NOT ContainsSequenceResult[CDSatellites.GetSatelliteRopes[selected.ob]] THEN { TerminalIO.PutF["*** Warning: there is no satellite of the form 'Keyword: Expression', where 'Keyword' is one of the following:"]; FOR i: NAT IN [0 .. nbSequenceKeyWords) DO TerminalIO.PutF[" %g", IO.rope[sequenceKeyWords[i]]] ENDLOOP; TerminalIO.PutF["\n"]; } ELSE TerminalIO.PutF["Sequencing of %g done.\n", IO.rope[CDDirectory.Name[selected.ob]]]; FlushCache[selected.ob]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, StripResultExprs[exprs]]; CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractSequence]; CDProperties.PutObjectProp[selected.ob, $IconFor, NIL]; }; MakeInvisibleToExtractor: PROC [comm: CDSequencer.Command] = { nInstances: INT _ 0; FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO inst: CD.Instance _ w.first; IF inst.selected THEN { CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, $ExtractNull]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.PutF["Made %g instances invisible to Sisyph\n", IO.int[nInstances]] }; MakeVisibleToExtractor: PROC [comm: CDSequencer.Command] = { nInstances: INT _ 0; FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO inst: CD.Instance _ w.first; IF inst.selected THEN { CDProperties.PutInstanceProp[inst, Sisyph.mode.extractProcProp, NIL]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.PutF["Made %g instances visible to Sisyph\n", IO.int[nInstances]] }; FlushCache: PROC [obj: CD.Object] = { FlushEachInstance: CDCells.InstEnumerator = {FlushCache[inst.ob]}; Sinix.FlushCache[obj]; IF CDCells.IsCell[obj] THEN [] _ CDCells.EnumerateInstances[obj, FlushEachInstance]; }; FlushSisyphCaches: PROC [comm: CDSequencer.Command] = { FOR w: LIST OF CD.Instance _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO IF w.first.selected THEN FlushCache[w.first.ob]; ENDLOOP; }; ShowInstExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Instance Expressions:\n"]; PutRopes[NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]]; }; AddInstExpression: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Instance Expression\n"]; exprs _ NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]; exprs _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs]; CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs] }; EditInstExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Instance Expressions\n"]; exprs _ NARROW[CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]; exprs _ EditExpressions[exprs, "Expression"]; CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs] }; ShowObjExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Object Expressions:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]]; IF NOT CDImports.IsImport[selected.ob] THEN RETURN; IF NARROW [selected.ob.specific, CDImports.ImportSpecific].boundInstance=NIL THEN {TerminalIO.PutF["Object is an unbound import.\n"]; RETURN}; TerminalIO.PutF["Object Expressions of the bound import:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[NARROW [selected.ob.specific, CDImports.ImportSpecific].boundInstance.ob, Sisyph.expressionsProp]]]; }; AddObjExpression: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Object Expression\n"]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs] }; EditObjExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Object Expressions\n"]; exprs _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ EditExpressions[exprs, "Expression"]; CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs] }; ShowParmNames: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Parm Names:"]; parms _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; WHILE parms#NIL DO TerminalIO.PutF[Rope.Cat["\n ", parms.first]]; parms _ parms.rest; ENDLOOP; TerminalIO.PutF["\n"]; }; AddParmName: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Add Parameter Name\n"]; parms _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; parms _ CONS [TerminalIO.RequestRope[Rope.Cat[" New Parameter: "]], parms]; CDProperties.PutObjectProp[selected.ob, Sisyph.parmNamesProp, parms] }; EditParmNames: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; parms: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.PutF["Edit Object Expressions\n"]; parms _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; parms _ EditExpressions[parms, "Parameter"]; CDProperties.PutObjectProp[selected.ob, Sisyph.parmNamesProp, parms] }; AlignUpToGrid: PROC [x, grid: CD.Number] RETURNS [CD.Number] ~ { RETURN [IF x>=0 THEN ((x+grid-1)/grid)*grid ELSE (x/grid)*grid] }; AlignDownToGrid: PROC [x, grid: CD.Number] RETURNS [CD.Number] ~ { RETURN [IF x>=0 THEN (x/grid)*grid ELSE ((x-grid+1)/grid)*grid] }; AlignPositionUpToGrid: PROC [p: CD.Position, grid: CD.Number] RETURNS [CD.Position] ~ { RETURN [[AlignUpToGrid[p.x, grid], AlignUpToGrid[p.y, grid]]] }; AlignRectUpToGrid: PROC [r: CD.Rect, grid: CD.Number] RETURNS [CD.Rect] ~ { RETURN [[x1: AlignDownToGrid[r.x1, grid], x2: AlignUpToGrid[r.x2, grid], y1: AlignDownToGrid[r.y1, grid], y2: AlignUpToGrid[r.y2, grid]]] }; MoveInstances: PROC [list: CD.InstanceList, by: CD.Position] ~ { WHILE list#NIL DO list.first.trans.off _ CDBasics.AddPoints[list.first.trans.off, by]; list _ list.rest; ENDLOOP; }; BuildIconSides: PROC [icon: Icon] RETURNS [sideSize: ARRAY CoreGeometry.Side OF CD.Position, sideList: ARRAY CoreGeometry.Side OF CD.InstanceList] ~ { BuildSideGeometry: PROC [on: CoreGeometry.Side, rotate: CD.Orientation, useTextEnd: BOOL, textOffset: CD.Position, pinStartPos: CD.Position] ~ { iList: CD.InstanceList _ NIL; pinPos, satPos: CD.Position; -- real ones pinPos _ pinStartPos; FOR names: ROPES _ icon.pins[on], names.rest WHILE names#NIL DO satObject: CD.Object = CDTexts.Create[text: names.first, font: icon.font]; size: CD.Position = CDBasics.SizeOfRect[satObject.bbox]; pinObject: CD.Object = CDRects.CreateRect[size: icon.pinRect, l: CD.commentLayer]; satInst, pinInst: CD.Instance; pinInst _ CDInstances.NewInst[pinObject, [pinPos, rotate]]; satPos _ CDBasics.AddPoints[pinPos, textOffset]; satPos _ CDBasics.SubPoints[ satPos, IF CDBasics.IncludesOddRot90[rotate] THEN [size.y/2, IF useTextEnd THEN 0 ELSE -size.x] ELSE [IF useTextEnd THEN size.x ELSE 0, size.y/2] ]; satInst _ CDInstances.NewInst[satObject, [satPos, rotate]]; pinPos _ AlignPositionUpToGrid[CDBasics.AddPoints[pinPos, CDBasics.OrientedSize[[0, size.y], rotate]], icon.grid]; CDSatellites.Associate[master: pinInst, text: satInst]; iList _ CONS[pinInst, iList]; iList _ CONS[satInst, iList]; ENDLOOP; IF iList#NIL THEN { -- Compute size (not default) and set logical base at [0,0] r: CD.Rect = AlignRectUpToGrid[CDInstances.BoundingRectO[iList], icon.grid]; pos: CD.Position = CDBasics.BaseOfRect[r]; sideSize[on] _ CDBasics.SizeOfRect[r]; MoveInstances[iList, CDBasics.NegOffset[pos]]; } ELSE sideSize[on] _ [0, 0]; sideList[on] _ iList; }; BuildSideGeometry[on: top, rotate: rotate270, useTextEnd: TRUE, textOffset: [0, -icon.pinRect.x-icon.guard], pinStartPos: [0, -icon.pinRect.x]]; BuildSideGeometry[on: bottom, rotate: rotate270, useTextEnd: FALSE, textOffset: [0, icon.pinRect.x-icon.guard], pinStartPos: [0, 0]]; BuildSideGeometry[on: right, rotate: original, useTextEnd: TRUE, textOffset: [-icon.guard, 0], pinStartPos: [-icon.pinRect.x, 0]]; BuildSideGeometry[on: left, rotate: original, useTextEnd: FALSE, textOffset: [icon.pinRect.x+icon.guard, 0], pinStartPos: [0, 0]]; }; BuildIconFrame: PROC [icon: Icon, box: CD.Rect] RETURNS [list: CD.InstanceList _ NIL] ~ { BuildBoxSide: PROC [size, at: CD.Position, orient: CD.Orientation] ~ { list _ CONS [CDInstances.NewInst[CDRects.CreateRect[size: size, l: CD.commentLayer], [at, orient]], list]; CDProperties.PutInstanceProp[list.first, Sisyph.mode.extractProcProp, $ExtractNull]; }; w: CD.Number = icon.boxWidth; BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x1, box.y1], orient: original]; -- left BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x2, box.y1], orient: original]; -- right BuildBoxSide[size: [w, w+box.x2-box.x1], at: [box.x2+w, box.y1], orient: rotate90]; -- bottom BuildBoxSide[size: [w, w+box.x2-box.x1], at: [box.x2+w, box.y2], orient: rotate90]; -- top }; CommentText: PROC [text: ROPE, font: CDTexts.CDFont] RETURNS [ob: CD.Object] ~ { IsItalic: PROC [fontName: ROPE] RETURNS [BOOL] = { RETURN [Rope.Find[fontName, "i", Rope.Length[fontName]-1, FALSE]#-1] }; italicFont: CDTexts.CDFont _ IF ~IsItalic[font.supposedName] THEN CDTexts.MakeFont[ name: Rope.Cat[font.supposedName, "I"], scale: font.scaleI] ELSE font; ob _ CDTexts.Create[text: text, font: italicFont]; }; BuildIconObject: PROC [icon: Icon, design: CD.Design] RETURNS [obj: CD.Object] ~ { sideSize: ARRAY CoreGeometry.Side OF CD.Position; sideList: ARRAY CoreGeometry.Side OF CD.InstanceList; internalInstances: CD.InstanceList _ NIL; iconFullName: ROPE = Rope.Cat[icon.name, ".icon"]; iconTextObject: CD.Object = CommentText[text: icon.name, font: icon.font]; size: CD.Position = CDBasics.SizeOfRect[iconTextObject.bbox]; iconText: CD.Instance; inside, outside: CD.Rect; width, height: CD.Number; IF icon.grid<=0 THEN icon.grid _ design.technology.lambda; [sideSize, sideList] _ BuildIconSides[icon]; width _ sideSize[left].x+sideSize[right].x+MAX[ sideSize[bottom].x, sideSize[top].x, AlignUpToGrid[2*size.x, icon.grid]]; height _ MAX[ sideSize[left].y, sideSize[right].y, sideSize[bottom].y+sideSize[top].y+AlignUpToGrid[4*size.y, icon.grid]]; inside.x1 _ sideSize[left].x; inside.y1 _ sideSize[bottom].y; inside.x2 _ width+icon.pinRect.y-sideSize[right].x; inside.y2 _ height+icon.pinRect.y-sideSize[top].y; outside.x1 _ IF sideList[left]=NIL THEN 0 ELSE icon.pinRect.x; outside.y1 _ IF sideList[bottom]=NIL THEN 0 ELSE icon.pinRect.x; outside.x2 _ IF sideList[right]=NIL THEN width ELSE width-icon.pinRect.x; outside.y2 _ IF sideList[top]=NIL THEN height ELSE height-icon.pinRect.x; MoveInstances[ sideList[bottom], [AlignDownToGrid[(width+sideSize[left].x-sideSize[right].x-sideSize[bottom].x)/2, icon.grid], 0]]; MoveInstances[ sideList[top], [AlignDownToGrid[(width+sideSize[left].x-sideSize[right].x-sideSize[top].x)/2, icon.grid], inside.y2]]; MoveInstances[ sideList[left], [0, AlignDownToGrid[(height-sideSize[left].y)/2, icon.grid]]]; MoveInstances[ sideList[right], [inside.x2, AlignDownToGrid[(height-sideSize[right].y)/2, icon.grid]]]; iconText _ CDInstances.NewInst[ iconTextObject, [CDBasics.SubPoints[CDBasics.Center[inside], CDBasics.Center[CDBasics.RectAt[[0, 0], size]]]]]; internalInstances _ BuildIconFrame[icon, outside]; internalInstances _ CONS [iconText, internalInstances]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO FOR list: CD.InstanceList _ sideList[on], list.rest WHILE list#NIL DO internalInstances _ CONS [list.first, internalInstances]; ENDLOOP; ENDLOOP; obj _ CDCells.CreateCell[il: internalInstances]; -- of course, one would really like a sequence! IF CDDirectory.Fetch[design, iconFullName].found THEN { TerminalIO.PutF["*** The icon %g already exists!\n", IO.rope[iconFullName]]; ERROR; }; IF NOT CDDirectory.Include[design, obj, iconFullName] THEN { TerminalIO.PutF["*** Direction insertion of icon %g failed.\n", IO.rope[iconFullName]]; ERROR; }; }; IconFromSchematic: PROC [cell: Core.CellType, schematicName, iconName: ROPE, design: CD.Design, grid: CD.Number _ -1] RETURNS [obj: CD.Object] ~ { InternalPin: TYPE ~ REF InternalPinRep; InternalPinRep: TYPE ~ RECORD [ name: ROPE, rect: CD.Rect -- The InstRectO of the pin, used to sort along the side ]; Side: TYPE ~ RECORD [ border: CD.Rect, -- Representation of schematic side pins: LIST OF InternalPin _ NIL ]; SearchPins: CoreOps.EachWireProc ~ { pinGeom: CoreGeometry.Instances _ CoreGeometry.GetPins[Sisyph.mode.decoration, wire]; pinName: ROPE = CoreOps.GetShortWireName[wire]; IF pinGeom=NIL THEN RETURN; IF pinName=NIL THEN { TerminalIO.PutF["*** The wire %g has pins, but no short name\n", IO.rope[CoreOps.GetFullWireName[root: cell.public, wire: wire]]]; RETURN[quit: TRUE]; }; WHILE pinGeom#NIL DO -- Paranoid! the first pin should touch a side of the schematic pinRect: CD.Rect = CoreGeometry.BBox[pinGeom.first]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO IF CDBasics.Intersect[pinRect, sides[on].border] THEN { sides[on].pins _ CONS [NEW [InternalPinRep _ [name: pinName, rect: pinRect]], sides[on].pins]; RETURN [subWires: FALSE]; }; ENDLOOP; pinGeom _ pinGeom.rest; ENDLOOP; TerminalIO.PutF["*** The wire %g has pins, but none of them touches the icon of the schematic.\n", IO.rope[CoreOps.GetFullWireName[root: cell.public, wire: wire]]]; RETURN [quit: TRUE]; }; XSort: GList.CompareProc ~ { -- Reverse order comparison RETURN [Basics.CompareINT[NARROW[ref2, InternalPin].rect.x1, NARROW[ref1, InternalPin].rect.x1]]; }; YSort: GList.CompareProc ~ { -- Reverse order comparison RETURN [Basics.CompareINT[NARROW[ref2, InternalPin].rect.y1, NARROW[ref1, InternalPin].rect.y1]]; }; lineWidth: CD.Number = CDLayers.LayerWidth[design, CD.commentLayer]; icon: Icon _ NEW [IconRep _ [name: iconName, boxWidth: lineWidth, pinRect: [x: 4*lineWidth, y: lineWidth], guard: 2*lineWidth, grid: grid, font: CDPanelFonts.CurrentFont[design]]]; sides: ARRAY CoreGeometry.Side OF Side; cellIR: CD.Rect = CD.InterestRect[CoreGeometry.GetObject[Sisyph.mode.decoration, cell]]; exprs: ROPES _ NIL; sides[top].border _ [x1: cellIR.x1, x2: cellIR.x2, y1: cellIR.y2, y2: cellIR.y2]; sides[bottom].border _ [x1: cellIR.x1, x2: cellIR.x2, y1: cellIR.y1, y2: cellIR.y1]; sides[right].border _ [x1: cellIR.x2, x2: cellIR.x2, y1: cellIR.y1, y2: cellIR.y2]; sides[left].border _ [x1: cellIR.x1, x2: cellIR.x1, y1: cellIR.y1, y2: cellIR.y2]; IF CoreOps.VisitWireSeq[cell.public, SearchPins] THEN RETURN [NIL]; FOR on: CoreGeometry.Side IN CoreGeometry.Side DO icon.pins[on] _ NIL; FOR list: LIST OF InternalPin _ NARROW [GList.UniqueSort[list: sides[on].pins, compareProc: IF on=top OR on=bottom THEN XSort ELSE YSort]], list.rest WHILE list#NIL DO icon.pins[on] _ CONS [list.first.name, icon.pins[on]]; ENDLOOP; ENDLOOP; obj _ BuildIconObject[icon, design]; exprs _ CONS [Rope.Cat[Sisyph.cellIconRope, " _ ES[\"", schematicName, "\", cx]"], exprs]; CDProperties.PutObjectProp[obj, Sisyph.mode.extractProcProp, NIL]; CDProperties.PutObjectProp[obj, Sisyph.expressionsProp, exprs]; CDProperties.PutObjectProp[obj, $IconFor, schematicName]; }; nbSequenceKeyWords: NAT = 5; sequenceKeyWords: ARRAY [0 .. nbSequenceKeyWords) OF ROPE = ["Seq", "SeqX", "SeqY", "RSeqX", "RSeqY"]; sequenceLayoutAtoms: ARRAY [0 .. nbSequenceKeyWords) OF ATOM = [NIL, $ArrayX, $ArrayY, $ReverseArrayY, $ReverseArrayY]; -- At this point, there is a strange dependency between Sisyph and PWCore, but it is not worth the effort making a separate module FindMatchingKeyword: PROC [expr: ROPE] RETURNS [keyword: NAT _ nbSequenceKeyWords, sequencing: ROPE _ NIL] = { FOR i: NAT IN [0 .. nbSequenceKeyWords) DO IF Rope.Match[Rope.Cat[sequenceKeyWords[i], ":*"], expr] THEN RETURN [i, Rope.Substr[expr, Rope.Find[expr, ":"]+1]]; ENDLOOP; }; IsSequenceResult: PROC [expr: ROPE] RETURNS [BOOL] = { RETURN [FindMatchingKeyword[expr].keyword#nbSequenceKeyWords] }; ContainsSequenceResult: PROC [exprs: ROPES] RETURNS [BOOL _ FALSE] = { WHILE exprs#NIL DO IF IsSequenceResult[exprs.first] THEN RETURN [TRUE]; exprs _ exprs.rest ENDLOOP; }; FindPorts: PROC [baseCell: CellType, wires: Wires] RETURNS [set: CoreClasses.SequenceSet] = { nats: LIST OF NAT _ NIL; size: NAT _ 0; WHILE wires#NIL DO FOR w: NAT IN [0 .. baseCell.public.size) DO sequenceName: ROPE _ CoreOps.GetShortWireName[wires.first]; IF wires.first=baseCell.public[w] OR (sequenceName#NIL AND Rope.Equal[sequenceName, CoreOps.GetShortWireName[baseCell.public[w]]]) THEN { nats _ CONS [w, nats]; size _ size + 1; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; wires _ wires.rest; ENDLOOP; set _ NEW [CoreClasses.SequenceSetRec[size]]; FOR i: INT IN [0 .. size) DO set[i] _ nats.first; nats _ nats.rest ENDLOOP; }; ExtractSequence: Sinix.ExtractProc = { AddProp: PROC [prop: ATOM, val: REF ANY] = { CoreProperties.PutCellTypeProp[cellType, prop, val]; }; cx: Sisyph.Context; resultRope: ROPE; cellType: CellType; name: ROPE = CDDirectory.Name[obj]; keyword: NAT; sequencing: ROPE; count: NAT; [cx, resultRope] _ Sisyph.EvaluateParameters[userData, obj, properties, IsSequenceResult]; IF resultRope=NIL THEN { TerminalIO.PutF["*** SisyphExtractSequence: Sequence does not contain any of sequencing information (e.g. an object satellite 'SeqX: 32').\n"]; ERROR; }; [keyword, sequencing] _ FindMatchingKeyword[resultRope]; Sisyph.Eval[cx, sequencing]; count _ NAT [Sisyph.FetchInt[cx, "&"].value]; TerminalIO.PutF["Extracting [Sisyph] cell %g (%g: %g)\n", IO.rope[CDDirectory.Name[obj]], IO.rope[sequenceKeyWords[keyword]], IO.int[count]]; cellType _ ExtractSequenceIcon[obj, cx, keyword, count]; props _ Sisyph.GetCoreInstProps[cx]; CoreProperties.Enumerate[Sisyph.GetCoreProps[cx], AddProp]; IF CoreOps.GetCellTypeName[cellType]=NIL AND name#NIL THEN [] _ CoreOps.SetCellTypeName[cellType, Rope.Substr[name, 0, Rope.Index[name, 0, "."]]]; result _ cellType; }; ExtractSequenceIcon: PROC [obj: CD.Object, cx: Sisyph.Context, keyword, count: NAT] RETURNS [sequence: CellType] = { iconCT: CellType = NARROW [Sinix.ExtractCell[obj, Sisyph.mode, NIL, cx].result]; iconRCT: CoreClasses.RecordCellType = NARROW [iconCT.data]; subCT: CellType; sequenceWires, flatSequenceWires: Wires _ NIL; IF iconRCT.size#1 THEN { TerminalIO.PutF["*** SisyphExtractSequence: Sequence should contain one and only one subcell.\n"]; ERROR; }; subCT _ iconRCT[0].type; Sisyph.ProcessGlobalNames[iconCT, cx]; FOR i: NAT IN [0 .. iconRCT.internal.size) DO wire: Wire = iconRCT.internal[i]; name: ROPE _ CoreOps.GetShortWireName[wire]; IF name=NIL THEN name _ "some wire"; IF NOT CoreOps.RecursiveMember[iconRCT[0].actual, wire] THEN { TerminalIO.PutF["*** SisyphExtractSequence: %g is not connected to subcell.\n", IO.rope[name]]; ERROR; }; IF NOT CoreOps.RecursiveMember[iconCT.public, wire] THEN { TerminalIO.PutF["*** SisyphExtractSequence: %g is not public.\n", IO.rope[name]]; ERROR; }; ENDLOOP; FOR i: NAT IN [0 .. subCT.public.size) DO IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $Sequence]#NIL THEN sequenceWires _ CONS [subCT.public[i], sequenceWires]; IF CoreProperties.GetWireProp[iconRCT[0].actual[i], $FlatSequence]#NIL THEN flatSequenceWires _ CONS [subCT.public[i], flatSequenceWires]; ENDLOOP; sequence _ CoreClasses.CreateSequence[NEW [CoreClasses.SequenceCellTypeRec _ [base: subCT, count: count, sequence: FindPorts[subCT, sequenceWires], flatSequence: FindPorts[subCT, flatSequenceWires]]]]; FOR i: NAT IN [0 .. sequence.public.size) DO iconWire: Wire = CoreClasses.CorrespondingActual[iconRCT[0], subCT.public[i]]; IF iconWire=NIL THEN ERROR; CoreGeometry.PutIndirectLazyPins[Sisyph.mode.decoration, sequence.public[i], iconWire]; CoreGeometry.PutGeometry[Sisyph.mode.decoration, sequence.public[i], CoreGeometry.GetGeometry[Sisyph.mode.decoration, iconWire]]; ENDLOOP; CoreGeometry.PutObject[Sisyph.mode.decoration, sequence, obj]; CoreProperties.PutCellTypeProp[sequence, $Layout, sequenceLayoutAtoms[keyword]]; }; PutRopes: PROC [ropes: ROPES] = { WHILE ropes#NIL DO TerminalIO.PutF["\t%g\n", IO.rope[ropes.first]]; ropes _ ropes.rest; ENDLOOP; }; IsSingleSelectedAndCell: PROC [selected: CD.Instance, multiple: BOOL] RETURNS [BOOL] = { IF ~IsSingleSelected[selected, multiple] THEN RETURN [FALSE]; IF ~CDCells.IsCell[selected.ob] THEN { TerminalIO.PutF["*** Selected instance is not a cellcan't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; IsSingleSelected: PROC [selected: CD.Instance, multiple: BOOL] RETURNS [BOOL] = { IF selected=NIL THEN { TerminalIO.PutF["*** No current selection--can't do it.\n"]; RETURN[FALSE]; }; IF multiple THEN { TerminalIO.PutF["*** Multiple instances selected--can't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; StripResultExprs: PROC [in: ROPES] RETURNS [out: ROPES _ NIL] = { FOR l: ROPES _ in, l.rest WHILE l#NIL DO IF ~Sisyph.IsResultExpression[l.first] THEN out _ CONS [l.first, out] ENDLOOP; }; EditExpressions: PROC [oldExprs: ROPES, prompt: ROPE] RETURNS [allExprs: ROPES _ NIL] = { input: ROPE; noOldExprs: BOOL _ oldExprs=NIL; TerminalIO.PutF["\n"]; WHILE oldExprs#NIL DO input _ TerminalIO.RequestRope[Rope.Cat[" ", prompt, ": ", oldExprs.first, " Replacement: "]]; SELECT TRUE FROM Rope.Equal[input, "-"] => TerminalIO.PutF[" ** Deleted\n"]; Rope.IsEmpty[input] => allExprs _ CONS [oldExprs.first, allExprs]; ENDCASE => allExprs _ CONS [input, allExprs]; oldExprs _ oldExprs.rest; ENDLOOP; IF noOldExprs THEN { input _ TerminalIO.RequestRope[Rope.Cat[" New ", prompt, ": "]]; WHILE ~Rope.IsEmpty[input] AND ~Rope.Equal[input, "-"] DO allExprs _ CONS [input, allExprs]; input _ TerminalIO.RequestRope[Rope.Cat[" New ", prompt, ": "]]; ENDLOOP; }; allExprs _ RopeList.Reverse[allExprs]; }; Sinix.RegisterExtractProc[$SisyphExtractSequence, ExtractSequence]; CDSequencer.ImplementCommand[key: $FlushSisyphCaches, proc: FlushSisyphCaches]; SinixOps.RegisterModeCommands[mode: Sisyph.mode]; [] _ CDPopUpMenus.MakeMenu[$SisyphIconMenu, "Sisyph: Make Icon", NIL]; CDSequencer.ImplementCommand[key: $CreateIconCommand, proc: CreateIconCommand]; CDSequencer.ImplementCommand[key: $MakeCellIconWithGeometryDef, proc: MakeCellIconWithGeometryDef]; CDSequencer.ImplementCommand[key: $MakeCellIconWithCodeDef, proc: MakeCellIconWithCodeDef]; CDSequencer.ImplementCommand[key: $MakeSequenceIcon, proc: MakeSequenceIcon]; CDSequencer.ImplementCommand[key: $MakeWireIconWithCodeDef, proc: MakeWireIconWithCodeDef]; CDSequencer.ImplementCommand[key: $UnMakeIcon, proc: UnMakeIcon]; [] _ CDPopUpMenus.MakeMenu[$SisyphVisibilityMenu, "Sisyph: Change Visibility", NIL]; CDSequencer.ImplementCommand[key: $MakeInvisibleToExtractor, proc: MakeInvisibleToExtractor]; CDSequencer.ImplementCommand[key: $MakeVisibleToExtractor, proc: MakeVisibleToExtractor]; [] _ CDPopUpMenus.MakeMenu[$SisyphParameterMenu, "Sisyph: Parameter Specification", NIL]; CDSequencer.ImplementCommand[key: $SisyphShowParmNames, proc: ShowParmNames, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddParmName, proc: AddParmName]; CDSequencer.ImplementCommand[key: $SisyphEditParmNames, proc: EditParmNames]; CDSequencer.ImplementCommand[key: $SisyphShowInstExpressions, proc: ShowInstExpressions, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddInstExpression, proc: AddInstExpression]; CDSequencer.ImplementCommand[key: $SisyphEditInstExpressions, proc: EditInstExpressions]; CDSequencer.ImplementCommand[key: $SisyphShowObjExpressions, proc: ShowObjExpressions, queue: doQueue]; CDSequencer.ImplementCommand[key: $SisyphAddObjExpression, proc: AddObjExpression]; CDSequencer.ImplementCommand[key: $SisyphEditObjExpressions, proc: EditObjExpressions]; END. .SisyphCmdsImpl.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Created by Pradeep Sindhu, December 9, 1985 10:01:52 pm PST Pradeep Sindhu, September 26, 1986 2:06:15 pm PDT Barth, January 13, 1986 3:30:05 pm PST Bertrand Serlet March 4, 1987 7:16:45 pm PST Jean-Marc Frailong June 20, 1986 8:25:11 pm PDT Last Edited by: Jacobi July 15, 1986 2:40:48 pm PDT Icon Commands User interface to create icon from schematic Other Commands Create icon from schematic Move all instances in the list by the required amount Build all the pins and pin names for the icon. Create geometry (pins and names) along an edge of the icon. All pins are aligned on grid coordinates. Text is centered on associated pin, at left or right according to request. Text is separated by guard CD units from the pin. The returned iLists alternates pins and names. Progress pin position Set satellite property and add to result list Build the geometry for the icon box Build the CD object for the icon in the design. The object is included in the design. Raises an ERROR if the object already existed (should be checked by caller). Compute a reasonable size for the inside and outside of the icon. Move the sides at their final locations and setup the icon name Build the icon object Build an icon straight from the schematic. Return NIL object if error. The schematicName had better be the right one. First, build rectangles representing the sides of the schematic Scan the public to build the sides structure Sort the pins on each side and setup the names in the icon structure Finally create the object from the icon structure Sequence Icons There should be only one subcell We deal with Global Variables we check that there is no internal only We compute which wires are going to be sequenced We create the sequence We copy the pins decorations The object decoration! We decorate with the appriopriate layout atom Internal Utilities Initialization FilterSch: SinixOps.FilterProc = {RETURN [Rope.Match["*.sch", name] OR Rope.Match["*.icon", name]]}; Main Menu SinixOps.RegisterBackgroundExtractionCommand[CD.FetchTechnology[$cmosB], Sisyph.mode, "Sch background extraction", $SchBackgroundExtract, FilterSch]; -- only works for CMosB. Not very clean Make Icon Menu Change Visibility Menu Make Parameter Menu (normally hidden) Expressions Menu ส!Y˜™Jšœ ฯmœ7™BJšœ8ฯk™;Jšœ.ž™1Icodešœ#ž™&Kšœ,™,Kšœ,ž™/Kšœ0ž™3—J™šž ˜ Jšœ˜Jšžœฌ˜ฎJšœ9˜9Jšœžœ˜Jšœ˜Jšœ%˜%J˜—šฯnœžœž˜Kšžœ žœ็žœ@˜ปKšžœž˜#K™Kšžœžœžœ˜Kš žœžœžœžœžœ˜Kšœžœ ˜Kšœžœ˜Kšœ žœ˜K˜Kšœžœžœ ˜šœ žœžœ˜Kšœžœžœฯc>˜PKšœ žœ  ˜3Kšœ žœ   ˜6Kšœžœ  #˜5Kšœžœ  +˜Kšœ žœ˜š žœžœžœžœ0žœžœž˜OKšœžœ˜šžœžœ˜KšœN˜NKšœ˜K˜K˜—Kšžœ˜—Kšœ;žœ˜NKšœ˜K˜—šŸœžœ ˜Kš œ žœžœžœžœ˜@Kš œ žœžœžœžœ˜IKš œ žœžœžœžœ˜IK™?šœ˜Jšœ˜Jšœb˜b—šœ˜Jšœ˜Jšœg˜g—šœ˜Jšœ˜Jšœ>˜>—šœ˜Jšœ˜JšœG˜G—šœ˜Jšœ˜Jšœ_˜_—J™Kšœ2˜2Jšœžœ˜7šžœžœž˜1š žœžœ(žœžœž˜EKšœžœ!˜9Kšžœ˜—Kšžœ˜—Kšœ1 /˜`šžœ/žœ˜7Kšœ5žœ˜LKšžœ˜K˜—–b[design: CD.Design, object: CD.Object, alternateName: ROPE _ NIL, fiddleName: BOOL _ TRUE]šžœžœ0žœ˜KšœPžœ ˜_Kšžœ˜Kšœ˜—šžœžœ.žœ˜:KšœBžœ ˜QKšžœ˜Kšœ˜—Jšžœ˜—Jšœ0™0šžœžœžœž˜)šžœ=žœ˜CJšžœžœ"˜;—šžœAžœ˜GJšžœžœ&˜C—Jšžœ˜—Jšœ™Jšœ&žœ ˜ษJšœ™šžœžœžœž˜,JšœN˜NJšžœ žœžœžœ˜JšœW˜WJšœ˜Jšžœ˜—J™Jšœ>˜>J™-JšœP˜PJ˜——™šŸœžœ žœ˜!šžœžœž˜Kšœžœ(˜DKšžœ˜—K˜K˜—š Ÿœžœ žœžœžœžœ˜XKšžœ'žœžœžœ˜=šžœžœ˜&KšœF˜FKšžœžœ˜K˜—Kšžœžœ˜ Kšœ˜—K˜š Ÿœžœ žœžœžœžœ˜Qšžœ žœžœ˜Kšœ<˜