WireIconExtrasImpl.mesa
Don Curry May 14, 1987 4:33:34 pm PDT
Last Edited by: Don Curry May 26, 1987 4:25:02 pm PDT
DIRECTORY CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDInstances, CDLayers, CDOps, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDViewer, Core, CoreCreate, CoreGeometry, CoreOps, CoreProperties, PopUpMenus, IO, PW, REFBit, Rope, SinixOps, Sisyph, TerminalIO, ViewerClasses, ViewerOps, WireIconExtras;
WireIconExtrasImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDCommandOps, CDDirectory, CDInstances, CDLayers, CDOps, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDTexts, CDViewer, CoreCreate, CoreGeometry, CoreProperties, CoreOps, IO, PW, REFBit, Rope, SinixOps, Sisyph, TerminalIO, ViewerOps
EXPORTS WireIconExtras =
BEGIN
ROPE: TYPE = Rope.ROPE;
Wire: TYPE = Core.Wire;
ConstructIconCommand: PROC [comm: CDSequencer.Command] ~ {
schFullName: ROPE;
iconName: ROPE;
icon:   CD.Object;
cell:   Core.CellType;
selected:  CD.Instance;
multiple:  BOOL;
cellRef:  REF;
sort:   BOOL;
[selected, multiple] ← CDOps.SelectedInstance[comm.design];
IF ~IsSingleSelectedAndCell[selected, multiple] THEN RETURN;
schFullName ← CDDirectory.Name[selected.ob, comm.design];
IF schFullName=NIL THEN
{TerminalIO.PutF["*** Selected schematic has no name.\n"]; RETURN};
IF NOT Rope.Match["*.sch", schFullName] 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};
iconName ← TerminalIO.RequestRope["Type icon short name: "];
IF Rope.IsEmpty[iconName]
THEN iconName ← IF Rope.Match["*.sch", schFullName]
THEN Rope.Substr[schFullName, 0, Rope.Length[schFullName]-4]
ELSE schFullName;
IF Rope.IsEmpty[schFullName] THEN
{TerminalIO.PutF["No name provided, no default from schematic.\n"]; RETURN};
IF CDDirectory.Fetch[comm.design, Rope.Cat[iconName, ".icon"]]#NIL THEN {
TerminalIO.PutF["*** The icon %g.icon already exists!\n", IO.rope[iconName]];
RETURN};
sort ← SELECT comm.key FROM
$ConstructIconCommand  => FALSE,
$ConstructIconCommandSort => TRUE,
ENDCASE       => ERROR;
icon ← IconFromSchematic[cell, schFullName, iconName, comm.design, sort];
IF icon=NIL THEN RETURN;
CDCells.SetSimplificationTreshhold[cell: icon, val: 30, inPixels: TRUE];
[]�Ops.IncludeObjectI[comm.design, icon, comm.pos]};
ConstructRecWireIconCommand: PROC [comm: CDSequencer.Command] ~ {
type: ROPE  ← TerminalIO.RequestRope["Type (eg. Def.Record): "];
wire: Core.Wire ← RecWire[type];
name: ROPE  ← type.Substr[type.Index[0,"."]+1];
icon: CD.Object ← ConstructWireIcon[comm, wire, name.Cat[".icon"]];
CDProperties.PutObjectProp[icon, $CodeFor, Rope.Cat["WireIconExtras.RecWire[\"", type, "\"]" ]];
CDProperties.PutObjectProp[icon, Sisyph.mode.extractProcProp, $SisyphExtractNamedWireIcon]};
ConstructDETWireIconCommand: PROC [comm: CDSequencer.Command] ~ {
type: ROPE  ← TerminalIO.RequestRope["Type (eg. Def.Enumerated): "];
pre: ROPE  ← TerminalIO.RequestRope["Prefix:"];
suf: ROPE  ← TerminalIO.RequestRope["Suffix:"];
wire: Core.Wire ← ETWire[pre, suf, type];
icon: CD.Object ← ConstructWireIcon[comm, wire, Rope.Cat[pre, suf, ".icon"]];
CDProperties.PutObjectProp
[icon, $CodeFor, IO.PutFR["WireIconExtras.ETWire[\"%g\", \"%g\", \"%g\"]",
IO.rope[pre], IO.rope[suf], IO.rope[type] ]];
CDProperties.PutObjectProp[icon, Sisyph.mode.extractProcProp, $SisyphExtractNamedWireIcon]};
ConstructWireIcon: PROC [comm: CDSequencer.Command, wire: Core.Wire, name: ROPE]
RETURNS[icon: CD.Object] ~ {
font:   CDTexts.CDFont ← CDPanelFonts.CurrentFont[comm.design];
w:    INT ← CDLayers.LayerWidth[comm.design, CD.commentLayer];
fw2:   INT ← font.height/2 - w - font.origin.y;
grid:   CD.Number ← Grid[comm.design, font];
insts:   CD.InstanceList ← NIL;
pinObject: CD.Object  ← CDRects.CreateRect[size: [grid/2, w], l: CD.commentLayer];
text:   CD.Object;
sat:   CD.Instance;
pin:   CD.Instance;
maxX:   INT ← 0;
FOR i: INT IN [0..wire.size) DO
text ← CDTexts.Create[CoreOps.GetShortWireName[wire[i]], font];
maxX ← MAX[ maxX, CD.InterestSize[text].x];
sat  ← CDInstances.NewInst[text,  [[x: grid, y: grid*(i+2)-fw2 ]]];
pin ← CDInstances.NewInst[pinObject, [[x: 0,  y: grid*(i+2)   ]]];
insts ← CONS[sat, CONS[pin, insts]];
CDSatellites.Associate[master: pin, text: sat] ENDLOOP;
text ← CDTexts.Create[CoreOps.GetShortWireName[wire], font];
maxX ← ((MAX[ maxX, CD.InterestSize[text].x] + 3*grid-1)/grid)*grid;
sat  ← CDInstances.NewInst[text,  [[x: maxX-grid-CD.InterestSize[text].x, y: grid-fw2 ]]];
pin ← CDInstances.NewInst[pinObject, [[x: maxX-grid/2,      y: grid  ]]];
insts ← CONS[sat, CONS[pin, insts]];
CDSatellites.Associate[master: pin, text: sat];
icon ← PW.CreateCell[instances: insts, ir: [0, 0, maxX, grid*(wire.size+2)+w]];
IF NOT CDDirectory.Include[comm.design, icon, name] THEN
{TerminalIO.PutF["*** Directory insertion of %g failed.\n", IO.rope[name]]; ERROR};
CDCells.SetSimplificationTreshhold[cell: icon, val: 30, inPixels: TRUE];
[]�Ops.IncludeObjectI[comm.design, icon, comm.pos]};
mark: ATOM ← CoreProperties.RegisterProperty[$TemporaryMark];
IconFromSchematic: PROC[
schCT: Core.CellType,
schFullName: ROPE,
iconName:  ROPE,
design:   CD.Design,
sort:    BOOL ]
RETURNS [iconObj: CD.Object] ~ {
L16: PROC[in: INT] RETURNS[INT] =
{XX: INT ← design.technology.lambda*16; RETURN[((in+XX-1)/XX)*XX]};
font:   CDTexts.CDFont ← CDPanelFonts.CurrentFont[design];
grid:   CD.Number ← Grid[design, font];
insts:   CD.InstanceList ← NIL;
schDeco:  CoreGeometry.Decoration ← Sisyph.mode.decoration;
schSize:  CD.Position ← CD.InterestSize[CoreGeometry.GetObject[schDeco, schCT]];
iconSize:  CD.Position;
hChans:  INT;
vChans:  INT;
iNmOb:  CD.Object ← CDTexts.Create[iconName, font];
pins:   ARRAY CoreGeometry.Side OF CD.InstanceList ← ALL[NIL];
cnt:   ARRAY CoreGeometry.Side OF NAT    ← ALL[0];
smax:   ARRAY CoreGeometry.Side OF INT     ← ALL[16];
w:    INT ← CDLayers.LayerWidth[design, CD.commentLayer];
fw2:   INT ← font.height/2 - w - font.origin.y;
iconFullName: ROPE ← iconName.Cat[".icon"];
pinObject:  CD.Object;
horWall:   CD.Object;
verWall:   CD.Object;
clearMark:  CoreOps.EachWireProc = {CoreProperties.PutWireProp[wire, mark, NIL]};
FOR side: CoreGeometry.Side IN CoreGeometry.Side DO
eachSortedPin: CoreGeometry.EachSortedPinProc = {
IF CoreProperties.GetWireProp[wire, mark]=NIL THEN {
text: CD.Object  ← CDTexts.Create[CoreOps.GetShortWireName[wire], font];
inst: CD.Instance ← CDInstances.NewInst[text];
CoreProperties.PutWireProp[wire, mark, mark];
pins[side]  ← CONS[inst, pins[side]];
cnt[side]   ← cnt[side] + 1;
smax[side]  ← MAX[ smax[side], CD.InterestSize[text].x] }};
[] ← CoreGeometry.EnumerateSortedSides[schDeco, schCT, side, eachSortedPin];
[]𡤌oreOps.VisitWire[schCT.public, clearMark];
ENDLOOP;
IF sort THEN FOR side: CoreGeometry.Side IN CoreGeometry.Side DO DO
ok: BOOLTRUE;
FOR insts: CD.InstanceList ← pins[side], insts.rest WHILE insts#NIL AND insts.rest#NIL DO
TwoObj: TYPE = RECORD[ob1, ob2: CD.Object];
r1: ROPENARROW[insts.first.ob.specific,  CDTexts.TextSpecific].text;
r2: ROPENARROW[insts.rest.first.ob.specific, CDTexts.TextSpecific].text;
SELECT Rope.Compare[r1, r2] FROM
less  => LOOP;
equal  => ERROR; ENDCASE;
[insts.first.ob, insts.rest.first.ob] ← TwoObj[insts.rest.first.ob, insts.first.ob];
ok←FALSE;
ENDLOOP;
IF ok THEN EXIT; ENDLOOP; ENDLOOP;
hChans  ← MAX[cnt[left], cnt[right]];
vChans  ← MAX[cnt[top], cnt[bottom]];
iconSize.x← L16[(vChans+4)*grid + 2*MAX[smax[left], smax[right],CD.InterestSize[iNmOb].x]];
iconSize.y← L16[(hChans+4)*grid + 2*MAX[smax[top], smax[bottom]]];
IF schSize.x > schSize.y
THEN iconSize.x ← L16[MAX[iconSize.x, (iconSize.y*schSize.x + schSize.y/2) /schSize.y]]
ELSE iconSize.y ← L16[MAX[iconSize.y, (iconSize.x*schSize.y + schSize.x/2) /schSize.x]];
pinObject ← CDRects.CreateRect[size: [grid/2, w], l: CD.commentLayer];
horWall ← CDRects.CreateRect[size: [iconSize.x, w], l: CD.commentLayer];
verWall ← CDRects.CreateRect[size: [w, iconSize.y], l: CD.commentLayer];
FOR side: CoreGeometry.Side DECREASING IN CoreGeometry.Side DO
tr: CD.Transformation ← SELECT side FROM
top  => [ [iconSize.x/2 - vChans*grid/2, iconSize.y],  rotate270 ],
bottom => [ [iconSize.x/2 - vChans*grid/2, 0],    rotate90 ],
left  => [ [0,    iconSize.y/2 - hChans*grid/2], original],
right  => [ [iconSize.x, iconSize.y/2 - hChans*grid/2], rotate180],
ENDCASE => ERROR;
index: INT ← (cnt[side]+(SELECT side FROM top,bottom=>vChans, ENDCASE => hChans)+1)/2;
FOR temp: CD.InstanceList ← pins[side], temp.rest WHILE temp#NIL DO
pin, sat: CD.Instance;
index ← index-1;
insts ← CONS[(sat ← temp.first), insts];
insts ← CONS[(pin ← CDInstances.NewInst[pinObject]), insts];
sat.trans.orient ← pin.trans.orient ← tr.orient;
CDSatellites.Associate[master: pin, text: sat];
SELECT side FROM
top  => {
pin.trans.off ← CDBasics.AddPoints[tr.off, [index*grid+0,   0  ]];
sat.trans.off ← CDBasics.AddPoints[tr.off, [index*grid+0-fw2, -grid ]]};
bottom => {
pin.trans.off ← CDBasics.AddPoints[tr.off, [index*grid+w,  0  ]];
sat.trans.off ← CDBasics.AddPoints[tr.off, [index*grid+w+fw2, +grid ]]};
left  => {
pin.trans.off ← CDBasics.AddPoints[tr.off, [0,  index*grid+0  ]];
sat.trans.off ← CDBasics.AddPoints[tr.off, [+grid, index*grid+0-fw2 ]]};
right  => {
pin.trans.off ← CDBasics.AddPoints[tr.off, [0,  index*grid+w  ]];
sat.trans.off ← CDBasics.AddPoints[tr.off, [-grid, index*grid+w+fw2 ]]};
ENDCASE => ERROR;
ENDLOOP;
ENDLOOP;
insts ← CONS[CDInstances.NewInst[horWall, [off:[0,     0    ]]], insts];
CDProperties.PutInstanceProp[insts.first, Sisyph.mode.extractProcProp, $ExtractNull];
insts ← CONS[CDInstances.NewInst[horWall, [off:[0,     iconSize.y-w ]]], insts];
CDProperties.PutInstanceProp[insts.first, Sisyph.mode.extractProcProp, $ExtractNull];
insts ← CONS[CDInstances.NewInst[verWall, [off:[0,     0    ]]], insts];
CDProperties.PutInstanceProp[insts.first, Sisyph.mode.extractProcProp, $ExtractNull];
insts ← CONS[CDInstances.NewInst[verWall, [off:[iconSize.x-w, 0    ]]], insts];
CDProperties.PutInstanceProp[insts.first, Sisyph.mode.extractProcProp, $ExtractNull];
insts ← CONS[CDInstances.NewInst[iNmOb, [off:[grid,   iconSize.y-2*grid ]]], insts];
iconObj ← PW.CreateCell[instances: insts];
IF NOT CDDirectory.Include[design, iconObj, iconFullName] THEN
{TerminalIO.PutF["*** Directory insertion of %g failed.\n", IO.rope[iconFullName]]; ERROR};
CDProperties.PutObjectProp[iconObj, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon];
CDProperties.PutObjectProp[iconObj, $IconFor,       schFullName]};
Grid: PROC[design: CD.Design, font: CDTexts.CDFont ← NIL] RETURNS[grid: NAT] = {
viewers: CDViewer.ViewerList ← CDViewer.ViewersOf[design];
IF viewers#NIL
THEN WITH ViewerOps.GetViewer[viewers.first, $Grid] SELECT FROM
rgrid: REF CD.Number => grid ← rgrid^; ENDCASE => NULL
ELSE grid ← design.technology.lambda*2;
IF font#NIL THEN WHILE font.height > (grid*4)/3 DO grid ← grid*2 ENDLOOP};
SisyphExtractAndStaticLeafConnections: PROC [comm: CDSequencer.Command] = {
root, cellType: Core.CellType;
cutSet:   CoreFlat.CutSet;
[root: root, cell: cellType] ← SinixOps.SelectedCellType[comm.design, Sisyph.mode];
IF root=NIL THEN RETURN; -- Extraction ended in error, message already printed
TerminalIO.PutF["\nStatic checking (Leaf connections) %g.\n",
IO.rope[CoreOps.GetCellTypeName[cellType]]];
cutSet ← IF CoreProperties.GetCellTypeProp[cellType, Static.staticCutSetProp]=NIL
THEN CoreFlat.CreateCutSet[labels: LIST["Logic", "LogicMacro"]]
ELSENIL;
Static.CountLeafConnections[cellType, Static.CheckCount, cutSet];
TerminalIO.PutF["Finished static checking %g.\n",
IO.rope[CoreOps.GetCellTypeName[cellType]]]};
LayoutStructureAndDrcCheckOfSelectedIcons: PROC [comm: CDSequencer.Command] = {
count:  INT ← 0;
drcErrors:  INT ← 0;
errs:  INT ← 0;
result:  REF;
badguys:  LIST OF ROPE;
objName:  ROPE;
errorMsg:  ROPE;
errorType: ATOM;
sourceCT:  Core.CellType;
indirectOb: CD.Object;
directOb:  CD.Object;
directCT:  Core.CellType;
drcAtomDesign: ATOM ← DesignRules.FetchRulesID[comm.design];
drcAtom:   ATOMIF drcAtomDesign#NIL THEN drcAtomDesign ELSE $VTI;
rules:    DesignRules.Rules ← DesignRules.GetRuleSet[drcAtom];
tech:    Drc.Tech ← DrcCMOSB.NewTechnology[DrcCMOSB.cMosBcompleteKey, rules];
IF comm.design.actual.rest#NIL THEN
{TerminalIO.PutF["Can't handle pushed in cell\n"]; RETURN};
TerminalIO.PutF["Using %g design rules\n", IO.atom[drcAtom]];
FOR w: CD.InstanceList ← CDOps.InstList[comm.design], w.rest WHILE w#NIL DO
IF NOT w.first.selected THEN LOOP;
objName ← CDDirectory.Name[w.first.ob, comm.design];
IF Rope.Find[objName, ".icon"]=-1 THEN
{TerminalIO.PutF["%g is not an icon.\n", IO.rope[objName]]; LOOP};
result ← SinixOps.ExtractCDInstance[w.first, comm.design, Sisyph.mode].result;
IF result=NIL OR NOT ISTYPE[result, Core.CellType] THEN
{TerminalIO.PutF["%g does not extract as a cell.\n", IO.rope[objName]]; LOOP};
sourceCT ← NARROW[result];
errorType ← NIL;
indirectOb ← PWCore.Layout[sourceCT !
PWCore.Error => {errorType ← type; errorMsg ← message; CONTINUE}];
IF errorType#NIL THEN {
TerminalIO.PutF["Cell for %g has Layout %g ERROR\n %g.\n",
IO.rope[objName], IO.atom[errorType], IO.rope[errorMsg]]; LOOP};
PWCoreLichen.Compare[sourceCT];
TerminalIO.PutF["Done extracting and comparing.\n"];
directOb ← CDDirectory.Expand1[indirectOb].new;
IF directOb=NIL THEN ERROR;
directCT ← NARROW[Sinix.Extract[directOb, PWCore.extractMode].result];
IF directCT=NIL THEN ERROR;
errs ← Drc.CheckDesignRules[directCT, CoreOps.CopyWire[directCT.public], tech, TRUE, NIL, PWCore.extractMode.decoration];
TerminalIO.PutF[" %2g errors in %g.\n", IO.int[errs],
IO.rope[CoreOps.GetCellTypeName[directCT]]];
IF errs#0 THEN {
[]�ug.Draw[directOb, comm.design.technology, objName];
badguys ← CONS[objName, badguys]};
drcErrors ← drcErrors+errs;
count ← count+1;
ENDLOOP;
TerminalIO.PutF["%2g drc errors in %g cells.\n", IO.int[drcErrors], IO.int[count]];
FOR badguys ← badguys, badguys.rest WHILE badguys#NIL DO
TerminalIO.PutF[" %g\n", IO.rope[badguys.first]]; ENDLOOP};
AddProp: PROC [comm: CDSequencer.Command] ~ {
selected: CD.Instance; multiple: BOOL;
[selected, multiple] ← CDOps.SelectedInstance[comm.design];
IF ~IsSingleSelected[selected, multiple] THEN RETURN;
IF selected.ob.immutable THEN
{TerminalIO.PutRope["*** Can't modify an immutable object\n"]; RETURN};
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, (SELECT comm.key FROM
$AWireAddProp => $SisyphExtractUnNamedWireIcon,
$PWireAddProp  => $SisyphExtractNamedWireIcon,
ENDCASE    => ERROR)]};
DelProp: PROC [comm: CDSequencer.Command] ~ {
selected: CD.Instance; multiple: BOOL;
[selected, multiple] ← CDOps.SelectedInstance[comm.design];
IF ~IsSingleSelected[selected, multiple] THEN RETURN;
IF selected.ob.immutable THEN
{TerminalIO.PutRope["*** Can't modify an immutable object\n"]; RETURN};
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, NIL]};
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]};
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 cell—can't do it.\n"]; RETURN[FALSE]};
RETURN[TRUE]};
GridComposer: PW.GeneratorProc = {
name: ROPE;
grid: INT ← Grid[design];
n:  INT ← TerminalIO.RequestInt["Size of the composer? "];
w:  INT ← CDLayers.LayerWidth[design, CD.commentLayer];
IF n<1 THEN {TerminalIO.PutF["*** Invalid parameter.\n"]; RETURN};
name ← IO.PutFR["Grid%gW%gComposer[%g].icon", IO.int[grid], IO.int[w], IO.int[n]];
ob ← CDDirectory.Fetch[design, name].object;
IF ob=NIL THEN {
ob ← GridComposeObj[design, grid, n].obj;
[] ← CDDirectory.Include[design, ob, name]}};
GridComposeWire: PUBLIC PROC[n: NAT] RETURNS [wire: Wire] ~ {
wire ← CoreOps.CreateWires[n, "w"];
FOR ii: INT IN [0..n)
DO wire[ii] ← CoreOps.CreateWires[0, IO.PutFR["w%g", IO.int[ii]]] ENDLOOP};
GridComposeObj: PROC [design: CD.Design, grid, n: INT]
RETURNS [obj: CD.Object] = {
Add: PROC[name: ROPENIL, size, pos: CD.Position] = {
list ← CONS[CDInstances.NewInst[CDRects.CreateRect[size, CD.commentLayer], [pos]], list];
IF name#NIL THEN {
names: LIST OF ROPELIST[name];
CDProperties.PutInstanceProp[list.first, Sisyph.expressionsProp, names]}};
list: CD.InstanceList ← NIL;
w:  INT ← CDLayers.LayerWidth[design, CD.commentLayer];
l:  INTMAX[w, grid/4];
Add[size:[2*l, grid*2*n+w], pos:[l, 0]];
CDProperties.PutInstanceProp[list.first, Sisyph.mode.extractProcProp, $ExtractNull];
Add[name: "w", size:[l, w], pos:[0, grid]];
FOR ii: INT IN [0..n) DO
Add[name: IO.PutFR["w%g", IO.int[ii]], size:[l, w], pos:[3*l, (2*ii+1)*grid]] ENDLOOP;
obj ← PW.CreateCell[instances: list];
CDProperties.PutObjectProp
[obj, $CodeFor, IO.PutFR["WireIconExtras.GridComposeWire[%g]", IO.int[n]]];
CDProperties.PutObjectProp[obj, Sisyph.mode.extractProcProp, $SisyphExtractUnNamedWireIcon];
CDCells.SetSimplificationTreshhold[obj, 20]};
RecWire: PUBLIC PROC[rec: ROPE, dual: BOOLFALSE] RETURNS[wire: Wire] =
{RETURN[RefWire[REFBit.NEWFromName[rec], rec.Substr[rec.Index[0,"."]+1]]]};
RefWire: PUBLIC PROC[ref: REF, name: ROPE, dual: BOOLFALSE] RETURNS[wire: Wire] = {
ZeroIfOne: PROC[s: INT] RETURNS[INT] = {RETURN[IF s=1 THEN 0 ELSE s]};
fieldForm: REFBit.Format ← REFBit.Desc[ref].fieldForm;
wires:   LIST OF Wire ← NIL;
temp:   LIST OF Wire ← NIL;
FOR field: INT IN[0..fieldForm.size) DO
fieldName: ROPE ← BitRopeToSigRope[fieldForm[field].name];
SELECT fieldForm[field].bitSize FROM
1   =>
{wires ← CONS[CoreCreate.Seq[fieldName, IF dual THEN 2 ELSE 0], wires]};
>1   => {
fieldWire: Wire ← CoreOps.CreateWires[fieldForm[field].bitSize, fieldName];
wires ← CONS[fieldWire, wires];
FOR bit: INT IN[0..fieldWire.size) DO
fieldWire[bit] ← CoreCreate.Seq[NIL, IF dual THEN 2 ELSE 0] ENDLOOP};
ENDCASE => ERROR;
ENDLOOP;
temp ← wires; wires ← NIL;
FOR temp ← temp, temp.rest WHILE temp#NIL DO wires ← CONS[temp.first, wires] ENDLOOP;
wire ← CoreOps.CreateWire[wires, name]};
ETWire: PUBLIC PROC[prefix, suffix, type: ROPE] RETURNS[wire: Wire] = {
bitName, bitNameInv: ROPE;
refREF: REF ← REFBit.NEWFromName[type];
format: REFBit.Format ← REFBit.Desc[refREF].bitForm;
wire ← CoreOps.CreateWires[MAX[2, format.size], prefix.Cat[suffix]];
FOR i: INT IN[0..format.size) DO
bitName  ← BitRopeToSigRope[format[i].name];
bitNameInv ← BitRopeToSigRope[format[i].nameInv];
IF ((format.size#1) = (i+1=format.size)) = (bitName#NIL) THEN ERROR;
IF ((format.size#1) = (bitNameInv#NIL)) = (bitName#NIL) THEN ERROR;
IF bitName=NIL THEN bitName ← bitNameInv;
wire[i] ← CoreOps.CreateWires[0, prefix.Cat[bitName, suffix]];
IF format.size=1 THEN
wire[1] ← CoreOps.CreateWires[0, prefix.Cat[bitNameInv, suffix]];
ENDLOOP};
BitRopeToSigRope: PROC [name: ROPE] RETURNS [ROPE] ~ {
Cap: PROC[rope: ROPE, idx: INT] RETURNS[ROPE] = {
char: CHAR ← rope.Fetch[idx+1];
IF char IN ['a..'z] THEN char ← char + LOOPHOLE['A - 'a];
RETURN[IO.PutFR["%g", IO.char[char]]]};
IF name = NIL THEN RETURN[NIL];
name ← Rope.Cat[Cap[name, -1], name.Substr[1]];
DO-- remove peiods and Capitalize next letters until end or next char is number
index: INT ← name.Index[0, "."];
IF index+1 >= name.Length[] OR name.Fetch[index+1] IN ['0..'9] THEN RETURN[name];
name ← Rope.Cat[name.Substr[0,index], Cap[name, index], name.Substr[index+2]];
ENDLOOP };
CDCommandOps.RegisterWithMenu[
menu:  $SisyphIconMenu,
entry:  "Create Cell Icon from schematics - Grid 2",
doc:  "Pins on grid 2. Overall size in units of 16.",
key:  $ConstructIconCommand,
proc:  ConstructIconCommand ];
CDCommandOps.RegisterWithMenu[
menu:  $SisyphIconMenu,
entry:  "Create Cell Icon from schematics - Grid 2 - Sorted",
doc:  "Pins on grid 2. Overall size in units of 16. Names sorted.",
key:  $ConstructIconCommandSort,
proc:  ConstructIconCommand ];
CDCommandOps.RegisterWithMenu[
menu:  $SisyphIconMenu,
entry:  "Create Wire Icon from Cedar Record Type",
doc:  "RECORDs with field types such as: RECORD, INT, BOOL, enumerated, subranges",
key:  $ConstructRecWireIconCommand,
proc:  ConstructRecWireIconCommand ];
CDCommandOps.RegisterWithMenu[
menu:  $SisyphIconMenu,
entry:  "Create Wire Icon from Cedar Enumerated Type",
doc:  "Decoded Enumerated types encoded as: 0, 3, 5, 9, 17 etc.",
key:  $ConstructDETWireIconCommand,
proc:  ConstructDETWireIconCommand ];
menu: PopUpMenus.Menu ← CDPopUpMenus.MakeMenu[
key:  $AWireMenu,
header: "Sisyph: Anonymous Wire extraction",
doc:  "Change Wire extraction property" ];
CDCommandOps.RegisterWithMenu[
menu:   $OtherProgramMenu,
entry:   "Sisyph: Anonymous/Public Wire",
doc:  "Change Anonymous or Public Wire extraction property",
key:  $AWireMenu,
proc:  NIL];
CDCommandOps.RegisterWithMenu[
menu:  $AWireMenu,
entry:  "Make Wire Anonymous",
doc:  "Forces Sisyph extraction to return a wire with all names removed. In the case of cell extraction, the result is the anonymous public.",
key:  $AWireAddProp,
proc:  AddProp];
CDCommandOps.RegisterWithMenu[
menu:  $AWireMenu,
entry:  "Make Wire Public",
doc:  "Forces Sisyph extraction to return a wire even when the result would normally be a cell.",
key:  $PWireAddProp,
proc:  AddProp];
CDCommandOps.RegisterWithMenu[
menu:  $AWireMenu,
entry:  "Default Wire",
doc:  NIL,
key:  $AWireDelProp,
proc:  DelProp];
CDCommandOps.RegisterWithMenu[
menu:  $OtherProgramMenu,
entry:  "Sisyph Extract And Static (Leaf Connections)",
doc:  "Sisyph Extract And Static (Leaf Connections)",
key:  $SisyphExtractAndStaticLeafConnections,
proc:  SisyphExtractAndStaticLeafConnections];
CDCommandOps.RegisterWithMenu[
menu:  $OtherProgramMenu,
entry:  "Library Layout Check",
doc:  "Lichen structure check and design rule check of the layouts of all selected icons",
key:  $LayoutStructureAndDrcCheckOfSelectedIcons,
proc:  LayoutStructureAndDrcCheckOfSelectedIcons];
PW.RegisterGenerator[GridComposer, "Composer - variable grid and width"];
END.