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
];
Command Procs
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] ~ {
User interface to create icon from schematic
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]
};
Create icon from schematic
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] ~ {
Move all instances in the list by the required amount
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] ~ {
Build all the pins and pin names for the icon.
BuildSideGeometry:
PROC [on: CoreGeometry.Side, rotate:
CD.Orientation, useTextEnd:
BOOL, textOffset:
CD.Position, pinStartPos:
CD.Position] ~ {
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.
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];
Progress pin position
pinPos ← AlignPositionUpToGrid[CDBasics.AddPoints[pinPos, CDOrient.OrientedSize[[0, satObject.size.y], rotate]], icon.grid];
Set satellite property and add to result list
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] ~ {
Build the geometry for the icon box
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] ~ {
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).
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];
Compute a reasonable size for the inside and outside of the 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;
Move the sides at their final locations and setup the icon name
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]]]];
Build the icon object
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] ~ {
Build an icon straight from the schematic. Return NIL object if error. The schematicName had better be the right one.
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;
First, build rectangles representing the sides of the schematic
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];
Scan the public to build the sides structure
IF CoreOps.VisitWireSeq[cell.public, SearchPins]
THEN
RETURN [NIL];
Sort the pins on each side and setup the names in the icon structure
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;
Finally create the object from the icon structure
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];
};
Initialization
FilterSch: SinixOps.FilterProc = {
RETURN [Rope.Match["*.sch", name]
OR Rope.Match["*.icon", name]]};
Main Menu
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
Make Icon Menu
[] ← 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];
Change Visibility Menu
[] ← 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];
Make Parameter Menu
[] ← 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];
Expressions Menu
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.