<> <> <> <> <> <> <> <> <<>> DIRECTORY Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDMenus, CDOps, CDOrient, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, Core, CoreClasses, CoreOps, CoreGeometry, GList, IO, PW, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerClasses, ViewerOps; SisyphCmdsImpl: CEDAR PROGRAM IMPORTS Basics, CD, CDBasics, CDCells, CDDirectory, CDImports, CDInstances, CDLayers, CDMenus, CDOps, CDOrient, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDTexts, CDViewer, CoreOps, CoreGeometry, GList, IO, PW, Rope, RopeList, Sinix, SinixOps, Sisyph, TerminalIO, ViewerOps SHARES Sinix = BEGIN <<>> ROPE: TYPE = Rope.ROPE; ROPES: TYPE = LIST OF ROPE; Wire: TYPE = Core.Wire; 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 ]; <> cdIconForKey: ATOM = $IconFor; MakeIcon: PROC [comm: CDSequencer.Command] = { CDMenus.CallMenuAndExecute[$SisyphIconMenu, comm]; }; UnMakeIcon: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; exprs, news: ROPES; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN; FlushCache[selected.ob]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; WHILE exprs#NIL DO IF NOT Sisyph.IsResultExpression[exprs.first] THEN news _ CONS [exprs.first, news]; exprs _ exprs.rest; ENDLOOP; CDProperties.PutProp[selected.ob, cdIconForKey, NIL]; CDProperties.PutProp[selected.ob, Sisyph.expressionsProp, news]; }; ChangeVisibility: PROC [comm: CDSequencer.Command] = { CDMenus.CallMenuAndExecute[$SisyphVisibilityMenu, comm]; }; 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.PutProp[inst, Sisyph.mode.extractProcProp, $ExtractNull]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.WriteF["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.PutProp[inst, Sisyph.mode.extractProcProp, NIL]; nInstances _ nInstances+1; FlushCache[inst.ob] } ENDLOOP; TerminalIO.WriteF["Made %g instances visible to Sisyph\n", IO.int[nInstances]] }; FlushCache: PROC [obj: CD.Object] = { CDProperties.PutProp[obj, Sinix.cacheProp, NIL]; IF CDCells.IsCell[obj] THEN { cellPtr: CD.CellPtr _ NARROW [obj.specificRef]; FOR l: LIST OF CD.Instance _ cellPtr.contents, l.rest WHILE l#NIL DO FlushCache[l.first.ob]; ENDLOOP; }; }; 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; }; 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.WriteF["*** Convention for icons is to suffix them with '.icon'.\n"]; cellIconExpr _ PW.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.PutProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutProp[selected.ob, cdIconForKey, 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.WriteF["*** Convention for icons is to suffix them with '.icon'.\n"]; schematicName _ PW.RequestRope["Type schematic name: "]; IF CDDirectory.Fetch[comm.design, schematicName].object = NIL THEN { TerminalIO.WriteF["*** No such object in design.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.WriteF["*** 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.PutProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutProp[selected.ob, cdIconForKey, 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 _ PW.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.PutProp[selected.ob, Sisyph.expressionsProp, exprs]; CDProperties.PutProp[selected.ob, cdIconForKey, 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.WriteF["*** Selected schematic has no name.\n"]; RETURN; }; IF NOT Rope.Match["*.sch", schematicName] THEN TerminalIO.WriteF["*** 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.WriteF["*** Selected cell does not extract to Core CellType\n"]; RETURN; }; iconShortName _ PW.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.WriteF["No name provided, no default from schematic.\n"]; RETURN; }; IF CDDirectory.Fetch[comm.design, Rope.Cat[iconShortName, ".icon"]].found THEN { TerminalIO.WriteF["*** 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]; }; ShowInstExpressions: PROC [comm: CDSequencer.Command] = { selected: CD.Instance; multiple: BOOL; [selected, multiple] _ CDOps.SelectedInstance[comm.design]; IF ~IsSingleSelected[selected, multiple] THEN RETURN; TerminalIO.WriteF["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.WriteF["Add Instance Expression\n"]; exprs _ NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]; exprs _ CONS [PW.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.WriteF["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.WriteF["Object Expressions:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]]; IF NOT CDImports.IsImport[selected.ob] THEN RETURN; IF NARROW [selected.ob.specificRef, CDImports.ImportPtr].boundInstance=NIL THEN {TerminalIO.WriteF["Object is an unbound import.\n"]; RETURN}; TerminalIO.WriteF["Object Expressions of the bound import:\n"]; PutRopes[NARROW [CDProperties.GetObjectProp[NARROW [selected.ob.specificRef, CDImports.ImportPtr].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.WriteF["Add Object Expression\n"]; exprs _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]; exprs _ CONS [PW.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.WriteF["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.WriteF["Parm Names:"]; parms _ NARROW[CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; WHILE parms#NIL DO TerminalIO.WriteF[Rope.Cat["\n ", parms.first]]; parms _ parms.rest; ENDLOOP; TerminalIO.WriteF["\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.WriteF["Add Parameter Name\n"]; parms _ NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]; parms _ CONS [PW.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.WriteF["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.location _ CDBasics.AddPoints[list.first.location, 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.CreateText[text: names.first, font: icon.font]; pinObject: CD.Object = CDRects.CreateRect[size: icon.pinRect, l: CD.commentLayer]; satInst, pinInst: CD.Instance; pinInst _ CDInstances.NewInst[ob: pinObject, location: pinPos, orientation: rotate]; satPos _ CDBasics.AddPoints[pinPos, textOffset]; satPos _ CDBasics.SubPoints[ satPos, CDOrient.OrientedSize[ [IF useTextEnd THEN satObject.size.x ELSE 0,satObject.size.y/2], rotate]]; satInst _ CDInstances.NewInst[ob: satObject, location: satPos, orientation: rotate]; <> pinPos _ AlignPositionUpToGrid[CDBasics.AddPoints[pinPos, CDOrient.OrientedSize[[0, satObject.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: CDOrient.rotate270, useTextEnd: TRUE, textOffset: [0, -icon.guard], pinStartPos: [0, -icon.pinRect.x]]; BuildSideGeometry[on: bottom, rotate: CDOrient.rotate270, useTextEnd: FALSE, textOffset: [0, icon.pinRect.x+icon.guard], pinStartPos: [0, 0]]; BuildSideGeometry[on: right, rotate: CDOrient.original, useTextEnd: TRUE, textOffset: [-icon.guard, 0], pinStartPos: [-icon.pinRect.x, 0]]; BuildSideGeometry[on: left, rotate: CDOrient.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; IF size.x>size.y THEN { -- This trick is necessary for stretchy moves... orient _ CDOrient.rotate90; size _ [size.y, size.x]; } ELSE orient _ CDOrient.original; list _ CONS [CDInstances.NewInst[ob: CDRects.CreateRect[size: size, l: CD.commentLayer], location: at, orientation: orient], list]; CDProperties.PutProp[list.first, Sisyph.mode.extractProcProp, $ExtractNull]; }; w: CD.Number = icon.boxWidth; BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x1, box.y1]]; -- left BuildBoxSide[size: [w, w+box.y2-box.y1], at: [box.x2, box.y1]]; -- right BuildBoxSide[size: [w+box.x2-box.x1, w], at: [box.x1, box.y1]]; -- bottom BuildBoxSide[size: [w+box.x2-box.x1, w], at: [box.x1, box.y2]]; -- 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.CreateText[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]; iconText: CD.Instance; inside, outside: CD.Rect; width, height: CD.Number; cellPtr: CD.CellPtr; 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*iconTextObject.size.x, icon.grid]]; height _ MAX[ sideSize[left].y, sideSize[right].y, sideSize[bottom].y+sideSize[top].y+AlignUpToGrid[4*iconTextObject.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[ ob: iconTextObject, location: CDBasics.SubPoints[CDBasics.Center[inside], CDBasics.Center[CDBasics.RectAt[[0, 0], iconTextObject.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.CreateEmptyCell[]; cellPtr _ NARROW [obj.specificRef]; cellPtr.contents _ internalInstances; [] _ CDCells.RepositionCell[obj, NIL]; -- This is only to set all cell values OK IF CDDirectory.Fetch[design, iconFullName].found THEN { TerminalIO.WriteF["*** The icon %g already exists!\n", IO.rope[iconFullName]]; ERROR; }; IF NOT CDDirectory.Include[design, obj, iconFullName] THEN { TerminalIO.WriteF["*** 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: CD.InstanceList _ CoreGeometry.GetPins[Sisyph.mode.decoration, wire]; pinName: ROPE = CoreOps.GetShortWireName[wire]; IF pinGeom=NIL THEN RETURN; IF pinName=NIL THEN { TerminalIO.WriteF["*** 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 = CDInstances.InstRectO[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.WriteF["*** 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 = CoreGeometry.GetIR[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.PutProp[obj, Sisyph.expressionsProp, exprs]; CDProperties.PutProp[obj, $IconFor, schematicName]; }; <> PutRopes: PROC [ropes: ROPES] = { WHILE ropes#NIL DO TerminalIO.WriteF["\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.WriteF["*** 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.WriteF["*** No current selection--can't do it.\n"]; RETURN[FALSE]; }; IF multiple THEN { TerminalIO.WriteF["*** Multiple instances selected--can't do it.\n"]; RETURN[FALSE]; }; RETURN[TRUE]; }; StripResultExprs: PROC [in: ROPES] RETURNS [out: ROPES] = { out _ 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.WriteF["\n"]; WHILE oldExprs#NIL DO input _ PW.RequestRope[Rope.Cat[" ", prompt, ": ", oldExprs.first, " Replacement: "]]; SELECT TRUE FROM Rope.Equal[input, "-"] => TerminalIO.WriteF[" ** Deleted\n"]; Rope.IsEmpty[input] => allExprs _ CONS [oldExprs.first, allExprs]; ENDCASE => allExprs _ CONS [input, allExprs]; oldExprs _ oldExprs.rest; ENDLOOP; IF noOldExprs THEN { input _ PW.RequestRope[Rope.Cat[" New ", prompt, ": "]]; WHILE ~Rope.IsEmpty[input] AND ~Rope.Equal[input, "-"] DO allExprs _ CONS [input, allExprs]; input _ PW.RequestRope[Rope.Cat[" New ", prompt, ": "]]; ENDLOOP; }; allExprs _ RopeList.Reverse[allExprs]; }; <> FilterSch: SinixOps.FilterProc = {RETURN [Rope.Match["*.sch", name] OR Rope.Match["*.icon", name]]}; <
> CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: "Make Icon", p: MakeIcon, key: $SisyphMakeIcon, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: "Flush Sisyph Caches", p: FlushSisyphCaches, key: $FlushSisyphCaches, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $OtherProgramMenu, entry: "Change Visibility For Sisyph", p: ChangeVisibility, key: $SisyphChangeVisibility, queue: doQueueAndMark]; SinixOps.RegisterExtractCommand[mode: Sisyph.mode, prompt: "Sisyph Extract", key: $SisyphExtractSelectedObj]; SinixOps.RegisterHighlightCommand[mode: Sisyph.mode, prompt: "Highlight net in schematic", key: $HighlightNetInSchematic]; SinixOps.RegisterBackgroundExtractionCommand[CD.FetchTechnology[$cmosB], Sisyph.mode, "Sch background extraction", $SchBackgroundExtract, FilterSch]; -- only works for CMosB. Not very clean <> [] _ CDMenus.CreateMenu["Sisyph: Make Icon", $SisyphIconMenu]; CDMenus.ImplementCommandToCallMenu[$SisyphIconMenu, $SisyphIconMenu]; CDMenus.ImplementEntryCommand[menu: $SisyphIconMenu, entry: "Create cell icon from schematic", p: CreateIconCommand, key: $CreateIconCommand, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphIconMenu, entry: "Associate cell icon with schematic", p: MakeCellIconWithGeometryDef, key: $MakeCellIconWithGeometryDef, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphIconMenu, entry: "Associate cell icon with code", p: MakeCellIconWithCodeDef, key: $MakeCellIconWithCodeDef, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphIconMenu, entry: "Associate wire icon with code", p: MakeWireIconWithCodeDef, key: $MakeWireIconWithCodeDef, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphIconMenu, entry: "Dissociate icon from source", p: UnMakeIcon, key: $UnMakeIcon, queue: doQueueAndMark]; <> [] _ CDMenus.CreateMenu["Sisyph: Change Visibility", $SisyphVisibilityMenu]; CDMenus.ImplementCommandToCallMenu[$SisyphVisibilityMenu, $SisyphVisibilityMenu]; CDMenus.ImplementEntryCommand[menu: $SisyphVisibilityMenu, entry: "Make Invisible to Sisyph", p: MakeInvisibleToExtractor, key: $MakeInvisibleToExtractor, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphVisibilityMenu, entry: "Make Visible to Sisyph", p: MakeVisibleToExtractor, key: $MakeVisibleToExtractor, queue: doQueueAndMark]; <<>> <> [] _ CDMenus.CreateMenu["Sisyph: Parameter Specification", $SisyphParameterMenu]; CDMenus.ImplementCommandToCallMenu[$SisyphParameterMenu, $SisyphParameterMenu]; <<>> CDMenus.ImplementEntryCommand[menu: $SisyphParameterMenu, entry: "Show Parameter Names", p: ShowParmNames, key: $SisyphShowParmNames]; CDMenus.ImplementEntryCommand[menu: $SisyphParameterMenu, entry: "Add Parameter Name", p: AddParmName, key: $SisyphAddParmName, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SisyphParameterMenu, entry: "Edit Parameter Names", p: EditParmNames, key: $SisyphEditParmNames, queue: doQueueAndMark]; <> CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Show Instance Expressions (LI-Left)", p: ShowInstExpressions, key: $SisyphShowInstExpressions]; CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Add Instance Expression (LI-Middle)", p: AddInstExpression, key: $SisyphAddInstExpression, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Edit Instance Expressions (LI-Right)", p: EditInstExpressions, key: $SisyphEditInstExpressions, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Show Object Expressions (LO-Left)", p: ShowObjExpressions, key: $SisyphShowObjExpressions]; CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Add Object Expression (LO-Middle)", p: AddObjExpression, key: $SisyphAddObjExpression, queue: doQueueAndMark]; CDMenus.ImplementEntryCommand[menu: $SatellitesMenu, entry: "Edit Object Expressions (LO-Right)", p: EditObjExpressions, key: $SisyphEditObjExpressions, queue: doQueueAndMark]; END.