SisyphCmdsImpl.mesa
Copyright Ó 1985, 1986, 1987 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 April 28, 1988 12:23:59 pm PDT
Jean-Marc Frailong December 9, 1987 6:50:30 pm PST
Last Edited by: Jacobi July 15, 1986 2:40:48 pm PDT
Don Curry January 20, 1988 3:43:54 pm PST
DIRECTORY
CD, CDCells, CDCommandOps, CDDirectory, CDImports, CDOps, CDProperties, CDSatellites, CDSequencer,
Core, CoreClasses, CoreOps, CoreGeometry, CoreProperties,
IO, Rope, RopeList,
Sinix, SinixOps, Sisyph, SymTab,
TerminalIO, ViewerClasses;
SisyphCmdsImpl: CEDAR PROGRAM
IMPORTS CD, CDCells, CDCommandOps, CDDirectory, CDImports, CDOps, CDProperties, CDSatellites, CDSequencer, CoreClasses, CoreOps, CoreGeometry, CoreProperties, IO, Rope, RopeList, Sinix, SinixOps, Sisyph, SymTab, TerminalIO
SHARES Sinix, Sisyph = BEGIN
ROPE:  TYPE = Rope.ROPE;
ROPES: TYPE = LIST OF ROPE;
Wire:  TYPE = Core.Wire;
Wires:  TYPE = Core.Wires;
CellType: TYPE = Core.CellType;
Icon Commands
UnMakeIcon: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance ← TheCellInstance[comm.design, "UnMakeIcon\n"];
IF selected=NIL THEN RETURN;
CleanUpIconProperties[selected.ob];
TerminalIO.PutF
["UnMakeIcon of %g done.\n", IO.rope[CDDirectory.Name[selected.ob, comm.design]]]};
MakeCellIcon: PROC [comm: CDSequencer.Command] = {
key: ATOM;
rope, name: ROPE;
selected: CD.Instance ← TheCellInstance[comm.design, "MakeCellIcon\n"];
IF selected=NIL THEN RETURN;
name ← CDDirectory.Name[selected.ob, comm.design];
IF NOT Rope.Match["*.icon", name]
THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"];
SELECT TerminalIO.RequestSelection[Rope.Cat["MakeCellIcon of ", name], LIST ["From Code", "From Schematic"], "choice of the nature of the cell icon", LIST ["Code returns a CellType", "Schematic should extract as a CellType"]] FROM
1 => {
key ← $CodeFor; rope ← TerminalIO.RequestRope["Type code: "];
TerminalIO.PutF["done.\n"]};
2 => {
rope ← TerminalIO.RequestRope["Type schematic name: "];
IF Rope.IsEmpty[rope] AND Rope.Match["*.icon", name]
THEN rope ← Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-5], ".sch"];
IF CDDirectory.Fetch[comm.design, rope]=NIL THEN {
TerminalIO.PutF["*** No object '%g' in design.\n", IO.rope[rope]];
RETURN};
IF Rope.Equal[rope, name] THEN {
TerminalIO.PutF["*** You can't do that: same icon and sch name!\n"];
RETURN};
IF NOT Rope.Match["*.sch", rope] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"];
key ← $IconFor;
TerminalIO.PutF["%g made cell icon of %g.\n", IO.rope[name], IO.rope[rope]]};
ENDCASE => {TerminalIO.PutF["*** Not done.\n"]; RETURN};
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, key, rope];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]};
MakeWireIcon: PROC [comm: CDSequencer.Command] = {
key: ATOM;
rope, name: ROPE;
choice: INT;
selected: CD.Instance ← TheCellInstance[comm.design, "MakeWireIcon\n"];
IF selected=NIL THEN RETURN;
name ← CDDirectory.Name[selected.ob, comm.design];
IF NOT Rope.Match["*.icon", name]
THEN TerminalIO.PutF["*** Convention for icons is to suffix them with '.icon'.\n"];
choice ← TerminalIO.RequestSelection[
Rope.Cat["MakeWireIcon of ", name],
LIST ["From Code; Named", "From Code; UnNamed", "From Schematic; Named", "From Schematic; UnNamed"],
"choice of the nature of the cell icon",
LIST ["Code returns a Wire", "Code returns a Wire", "Schematic should extract as a CellType", "Schematic should extract as a CellType"] ];
SELECT choice FROM
1, 2 => {
key ← $CodeFor; rope ← TerminalIO.RequestRope["Type code: "];
TerminalIO.PutF["done.\n"]};
3, 4 => {
rope ← TerminalIO.RequestRope["Type schematic name: "];
IF Rope.IsEmpty[rope] AND Rope.Match["*.icon", name]
THEN rope ← Rope.Cat[Rope.Substr[name, 0, Rope.Length[name]-5], ".sch"];
IF CDDirectory.Fetch[comm.design, rope]=NIL THEN {
TerminalIO.PutF["*** No object '%g' in design.\n", IO.rope[rope]];
RETURN};
IF Rope.Equal[rope, name] THEN {
TerminalIO.PutF["*** You can't do that: same icon and sch name!\n"];
RETURN};
IF NOT Rope.Match["*.sch", rope] THEN TerminalIO.PutF["*** Convention for schematics is to suffix them with '.sch'.\n"];
key ← $IconFor;
TerminalIO.PutF["%g made wire icon of %g.\n", IO.rope[name], IO.rope[rope]]};
ENDCASE => {TerminalIO.PutF["*** Not done.\n"]; RETURN};
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, key, rope];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, SELECT choice FROM 1, 3 => $SisyphExtractNamedWireIcon, 2, 4 => $SisyphExtractUnNamedWireIcon, ENDCASE => ERROR]};
MakeSequenceIcon: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance ← TheCellInstance[comm.design, "MakeSequenceIcon\n"];
IF selected=NIL THEN RETURN;
CleanUpIconProperties[selected.ob];
CDProperties.PutObjectProp[selected.ob, Sisyph.mode.extractProcProp, $SisyphExtractSequence];
IF ParseSatellites[CDSatellites.GetSatelliteRopes[selected.ob]].keyword=NIL THEN TerminalIO.PutF["*** Warning: there is no satellite of the form 'Keyword: Expression'.\n"];
TerminalIO.PutF["Sequencing of %g done.\n", IO.rope[CDDirectory.Name[selected.ob, comm.design]]]};
Other Commands
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[comm.design, 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[comm.design, inst.ob]}
ENDLOOP;
TerminalIO.PutF["Made %g instances visible to Sisyph\n", IO.int[nInstances]]};
FlushCache: PROC [design: CD.Design, obj: CD.Object] = {
name: ROPE ← CDDirectory.Name[obj, design];
iconFor: REF = CDProperties.GetObjectProp[obj, $IconFor];
schName: ROPE = IF ISTYPE [iconFor, ROPE] THEN NARROW [iconFor] ELSE NIL;
sch: CD.Object = IF schName#NIL THEN CDDirectory.Fetch[design, schName] ELSE NIL;
FlushEachInstance: CDCells.InstEnumerator = {FlushCache[design, inst.ob]};
IF name=NIL AND (CDCells.IsCell[obj] OR CDImports.IsImport[obj]) THEN name ← CD.Describe[ob: obj, design: design];
IF (CDProperties.GetObjectProp[obj, $SinixInstanceCache]#NIL OR CDProperties.GetObjectProp[obj, $SinixObjectCache]#NIL) AND name#NIL
THEN TerminalIO.PutF["Flushing %g.\n", IO.rope[name]]; -- We use the property although it is PRIVATE because printing is just a hint
Sinix.FlushCache[obj];
IF CDCells.IsCell[obj]
THEN [] ← CDCells.EnumerateInstances[obj, FlushEachInstance];
IF sch#NIL
THEN FlushCache[design, sch]};
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[comm.design, w.first.ob];
ENDLOOP};
ShowInstExpressions: PROC [comm: CDSequencer.Command] = {
selected: CD.Instance ← CDOps.TheInstance[comm.design, "ShowInstExpressions\n"];
IF selected=NIL THEN RETURN;
PutRopes["Instance Expressions:\n", NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]]]};
AddInstExpression: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance ← CDOps.TheInstance[comm.design, "AddInstExpression\n"];
IF selected=NIL THEN RETURN;
exprs ← NARROW [CDProperties.GetInstanceProp[selected, Sisyph.expressionsProp]];
PutRopes["Add Instance Expression. Previous Instance Expressions:\n", exprs];
exprs ← CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs];
CDProperties.PutInstanceProp[selected, Sisyph.expressionsProp, exprs]};
EditInstExpressions: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance ← CDOps.TheInstance[comm.design, "EditInstExpressions\n"];
IF selected=NIL 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 ← CDOps.TheInstance[comm.design, "ShowObjExpressions\n"];
IF selected=NIL THEN RETURN;
PutRopes["Object Expressions:\n", NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]]];
IF NOT CDImports.IsImport[selected.ob] THEN RETURN;
IF NARROW [selected.ob.specific, CDImports.ImportSpecific].boundOb=NIL
THEN TerminalIO.PutF["Object is an unbound import.\n"]
ELSE PutRopes["Object Expressions of the bound import:\n", NARROW [CDProperties.GetObjectProp[NARROW [selected.ob.specific, CDImports.ImportSpecific].boundOb, Sisyph.expressionsProp]]]};
AddObjExpression: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance ← TheCellInstance[comm.design, "AddObjExpression\n"];
IF selected=NIL THEN RETURN;
exprs ← NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.expressionsProp]];
PutRopes["Add Object Expression. Previous Object Expressions:\n", exprs];
exprs ← CONS [TerminalIO.RequestRope[Rope.Cat[" New Expression: "]], exprs];
CDProperties.PutObjectProp[selected.ob, Sisyph.expressionsProp, exprs]};
EditObjExpressions: PROC [comm: CDSequencer.Command] = {
exprs: ROPES;
selected: CD.Instance ← TheCellInstance[comm.design, "EditObjExpressions\n"];
IF selected=NIL 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 ← CDOps.TheInstance[comm.design, "ShowParmNames\n"]; -- not TheCellInstance for discovering old settings
IF selected=NIL THEN RETURN;
PutRopes["Parameter Names (0 for no parameter):\n", NARROW [CDProperties.GetObjectProp[selected.ob, Sisyph.parmNamesProp]]]};
SetParmName: PROC [comm: CDSequencer.Command] = {
insts: LIST OF CD.Instance ← AllCellInstances[comm.design, "SetParmName\n"];
IF insts=NIL THEN RETURN;
SELECT TerminalIO.RequestSelection["Setting Parameters", LIST ["Explicitly", "Implicitly"], "Better ABORT and click the doc if you do not know what you are doing ...", LIST ["All selected cells with get the specified parameters", "Automatic program setting parameters"]] FROM
1 => {
parms: ROPESNIL;
DO
input: ROPE ← TerminalIO.RequestRope[" Parameter: "];
IF Rope.IsEmpty[input] THEN EXIT;
parms ← CONS [input, parms];
ENDLOOP;
WHILE insts#NIL DO
TerminalIO.PutF["Setting parameters on cell %g.\n", IO.rope[CD.Describe[ob: insts.first.ob, design: comm.design]]];
CDProperties.PutObjectProp[insts.first.ob, Sisyph.parmNamesProp, parms];
insts ← insts.rest;
ENDLOOP};
2 => {
IF TRUE THEN {TerminalIO.PutF["Not yet implemented.\n"]; RETURN};
WHILE insts#NIL DO
name: ROPE = CDDirectory.Name[object: insts.first.ob, design: comm.design];
parms: ROPES; reasonForWorld: ROPE;
[parms, reasonForWorld] ← ComputeParameters[comm.design, insts.first.ob, insts.first.properties];
IF reasonForWorld=NIL
THEN {
TerminalIO.PutF["Setting parameters on cell %g.\n", IO.rope[name]];
CDProperties.PutObjectProp[insts.first.ob, Sisyph.parmNamesProp, parms]}
ELSE TerminalIO.PutF["*** Could not set parameters for cell %g because %g.\n", IO.rope[name], IO.rope[reasonForWorld]];
insts ← insts.rest;
ENDLOOP};
ENDCASE => RETURN};
EditParmNames: PROC [comm: CDSequencer.Command] = {
parms: ROPES;
selected: CD.Instance ← TheCellInstance[comm.design, "EditParmNames\n"];
IF selected=NIL 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]};
Sequence Icons
sequenceKeyWords: SymTab.Ref ← SymTab.Create[5];
ParseSatellites: PROC [ropes: ROPES]
RETURNS [keyword, expr: ROPENIL, others: ROPESNIL] = {
WHILE ropes#NIL DO
tokenKind1, tokenKind2: IO.TokenKind; token1, token2: ROPE; rest: ROPE;
[tokenKind1, token1, rest] ← Sisyph.ParseRope[ropes.first];
[tokenKind2, token2, rest] ← Sisyph.ParseRope[rest];
IF tokenKind1=tokenID AND SymTab.Fetch[sequenceKeyWords, token1].found AND Sisyph.IsParsedChar[tokenKind2, token2, ':]
THEN IF keyword=NIL
THEN {keyword ← token1; expr ← rest}
ELSE {TerminalIO.PutF["*** SisyphExtractSequence: Conflicting sequencing satellites '%g:%g' and '%g'.\n", IO.rope[keyword], IO.rope[expr], IO.rope[ropes.first]]; ERROR}
ELSE others ← CONS [ropes.first, others];
ropes ← ropes.rest;
ENDLOOP};
FindPorts: PROC [baseCell: CellType, wires: Wires] RETURNS [set: CoreClasses.SequenceSet] = {
nats: LIST OF NATNIL;
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 = {
name: ROPE ← mode.nameProc[obj, userData];
cx: Sisyph.Context;
keyword, expr: ROPE;
others: ROPES;
cellType: CellType;
count: NAT;
[keyword, expr, others] ← ParseSatellites[NARROW [CDProperties.GetObjectProp[obj, Sinix.satellitesProp]]];
IF keyword=NIL THEN {
TerminalIO.PutF["*** SisyphExtractSequence: Sequence does not contain any of sequencing information (e.g. an object satellite 'SeqX: 32').\n"];
ERROR};
CDProperties.PutObjectProp[obj, Sinix.satellitesProp, others];
cx ← Sisyph.EvaluateParameters[userData, obj, properties];
Sisyph.EvalExpr[cx, keyword, expr, FALSE];
count ← NAT [Sisyph.FetchInt[cx, keyword].value];
Sinix.PutF["Extracting [Sisyph] cell %g (%g: %g)\n", IO.rope[name], IO.rope[keyword], IO.int[count]];
name ← Rope.Substr[name, 0, Rope.Index[name, 0, ".sch"]]; -- hack
name ← Rope.Substr[name, 0, Rope.Index[name, 0, ".icon"]]; -- hack
cellType ← ExtractSequenceIcon[obj, cx, keyword, count, name, Sisyph.GetCoreProps[cx]];
props ← Sisyph.GetCoreInstProps[cx];
result ← cellType};
ExtractSequenceIcon: PROC
[obj: CD.Object, cx: Sisyph.Context, resultVar: ROPE, count: NAT, name: ROPE, props: Core.Properties] RETURNS [sequence: CellType] = {
iconCT: CellType = NARROW [Sinix.ExtractCell[obj, Sisyph.mode, NIL, cx].result];
iconRCT: CoreClasses.RecordCellType = NARROW [iconCT.data];
subCT: CellType;
layoutAtom: REF;
sequenceWires, flatSequenceWires: Wires ← NIL;
There should be only one subcell
IF iconRCT.size#1 THEN {
TerminalIO.PutF["*** SisyphExtractSequence: Sequence should contain one and only one subcell.\n"];
ERROR};
subCT ← iconRCT[0].type;
We deal with Global Variables
Sisyph.ProcessGlobalNames[iconCT, cx];
we check that there is no internal only
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;
We compute which wires are going to be sequenced
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;
We create the sequence
sequence ← CoreClasses.CreateSequence[
args: NEW [CoreClasses.SequenceCellTypeRec ← [
base: subCT, count: count,
sequence: FindPorts[subCT, sequenceWires],
flatSequence: FindPorts[subCT, flatSequenceWires] ]],
name: name, props: props ];
New code to copy properties from the extracted public to the new sequence public.
FOR i: NAT IN [0..sequence.public.size) DO
iconWire: Wire = CoreClasses.CorrespondingActual[iconRCT[0], subCT.public[i]];
CopyWireProperties[from: iconWire, to: sequence.public[i]] ENDLOOP;
The object decoration!
CoreGeometry.PutObject[Sisyph.mode.decoration, sequence, obj];
We decorate with the appriopriate layout atom
layoutAtom ← SymTab.Fetch[sequenceKeyWords, resultVar].val;
IF layoutAtom#NIL THEN CoreProperties.PutCellTypeProp[sequence, $Layout, layoutAtom];
};
CopyWireProperties: PROC[from, to: Wire] = {
eachProp: PROC[atom:ATOM, ref: REF] = {CoreProperties.PutWireProp[to, atom, ref]};
CoreProperties.Enumerate[from.properties, eachProp]};
Computing Parameters
This function is, of course, slightly fancy ...
Not really working, either!
ComputeParameters: PROC [design: CD.Design, obj: CD.Object, properties: CD.PropList] RETURNS [parms: ROPES, reasonForWorld: ROPENIL] = {
cx: Sisyph.Context ← SymTab.Create[11];
parms ← NARROW [CDProperties.GetObjectProp[obj, Sisyph.parmNamesProp]];
IF parms#NIL THEN RETURN;
Sisyph.Store[cx, "design", NEW [CD.Design ← design]];
Sisyph.Insert[cx, "globalNames", NEW [ROPES ← Sisyph.defaultGlobalNames]];
[] ← Sinix.Extract[
obj: obj, mode: Sisyph.mode, properties: properties, userData: cx
! ANY  => {reasonForWorld ← "???"; GOTO Return} ];
parms ← LIST ["0"];
EXITS Return => RETURN};
Internal Utilities
PutRopes: PROC [rope: ROPE, ropes: ROPES] = {
TerminalIO.PutF[rope];
WHILE ropes#NIL DO
TerminalIO.PutF["\t%g\n", IO.rope[ropes.first]]; ropes ← ropes.rest;
ENDLOOP};
TheCellInstance: PROC [design: CD.Design, text: ROPENIL]
RETURNS [inst: CD.Instance ← NIL] = {
inst ← CDOps.TheInstance[design, text];
IF inst=NIL OR CDCells.IsCell[inst.ob] THEN RETURN;
TerminalIO.PutF["*** Selected instance is not a cell—can't do it.\n"];
inst ← NIL};
AllCellInstances: PROC [design: CD.Design, text: ROPENIL]
RETURNS [insts: LIST OF CD.Instance ← NIL] = {
IF text#NIL THEN TerminalIO.PutRope[text];
FOR w: CD.InstanceList ← CDOps.InstList[design], w.rest WHILE w#NIL DO
IF NOT w.first.selected THEN LOOP;
IF NOT CDCells.IsCell[w.first.ob]
THEN {TerminalIO.PutRope[" selection is not a cell; failed\n"]; RETURN [NIL]};
insts ← CONS [w.first, insts];
ENDLOOP;
IF insts=NIL THEN TerminalIO.PutRope[" no selection; failed\n"]};
CleanUpIconProperties: PROC [obj: CD.Object] = {
Sinix.FlushCache[obj];
CDProperties.PutObjectProp[obj, $IconFor, NIL];
CDProperties.PutObjectProp[obj, $CodeFor, NIL];
CDProperties.PutObjectProp[obj, Sisyph.mode.extractProcProp, NIL];
CDProperties.PutObjectProp[obj, Sisyph.expressionsProp, StripResultExprs
[NARROW [CDProperties.GetObjectProp[obj, Sisyph.expressionsProp]]]] };
Soon obsolete?
StripResultExprs: PROC [in: ROPES] RETURNS [out: ROPESNIL] = {
FOR l: ROPES ← in, l.rest WHILE l#NIL DO
expr: ROPE ← l.first;
IF NOT Rope.Match[expr, "*cI*←*"] AND NOT Rope.Match[expr, "*wI*←*"] AND NOT Rope.Match[expr, "*wire*←*"] THEN out ← CONS [expr, out]
ENDLOOP};
EditExpressions: PROC [oldExprs: ROPES, prompt: ROPE] RETURNS [allExprs: ROPESNIL] = {
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]};
Convertion code
MatchProc: TYPE = PROC [old: ROPE] RETURNS [BOOL];
MatchTransistor:  MatchProc = {RETURN [Rope.Match["*CreateTransistor[[*", old]]};
MatchAmpersand: MatchProc = {RETURN [Rope.Match["*&*←*", old]]};
MatchName:   MatchProc = {RETURN [Rope.Match["name ← \"*\"", old]]};
MatchSchCI:   MatchProc = {RETURN [Rope.Match["*cI*←*ES[\"*\",*cx]", old]]};
MatchCodeCI:   MatchProc = {RETURN [Rope.Match["*cI*←*", old]]};
MatchCodeWI:   MatchProc = {RETURN [Rope.Match["*wI*←*", old]]};
MatchWire:    MatchProc = {RETURN [Rope.Match["*wire*←*", old]]};
MatchDeclare:   MatchProc = {RETURN [Rope.Match[ "*Sisyph.Store[cx,*\"*\",*NEW[*←*]]", old]]};
Change: PROC [master: REF, location: ROPE] RETURNS [needInteraction: ROPENIL] = {
news: ROPES;
CDProperties.PutProp[master, $CameFrom, NIL];
CDProperties.PutProp[master, $OriginalName, NIL];
CDProperties.PutProp[master, $CDBringoverLibraryName, NIL];
CDProperties.PutProp[master, $SisyphArguments, NIL];
FOR list: ROPESNARROW [CDProperties.GetProp[master, Sisyph.expressionsProp]], list.rest WHILE list#NIL DO
old: ROPE = list.first;
SELECT TRUE FROM
MatchName[old] => {
new: ROPE = Rope.Substr[old, 8, Rope.Length[old]-9];
TerminalIO.PutF["changed '%g' to '%g'.\n", IO.rope[old], IO.rope[new]];
news ← CONS [new, news];
};
MatchSchCI[old] => {
pos1: INT ← Rope.Find[old, "\""];
pos2: INT ← Rope.Find[old, "\"", pos1+1];
sch: ROPE = Rope.Substr[old, pos1+1, pos2-pos1-1];
TerminalIO.PutF["changed '%g' to an $IconFor property '%g'.\n", IO.rope[old], IO.rope[sch]];
CDProperties.PutProp[master, $IconFor, sch];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]};
MatchCodeCI[old] => {
code: ROPE = Rope.Substr[old, Rope.Find[old, "←"]+1];
TerminalIO.PutF["changed '%g' to an $CodeFor property '%g'.\n", IO.rope[old], IO.rope[code]];
CDProperties.PutProp[master, $IconFor, NIL]; -- because $IconFor was not the truth in CD24!
CDProperties.PutProp[master, $CodeFor, code];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractCellIcon]};
MatchCodeWI[old] => {
code: ROPE = Rope.Substr[old, Rope.Find[old, "←"]+1];
TerminalIO.PutF["changed '%g' to an $CodeFor property '%g'.\n", IO.rope[old], IO.rope[code]];
CDProperties.PutProp[master, $CodeFor, code];
CDProperties.PutProp[master, Sisyph.mode.extractProcProp, $SisyphExtractNamedWireIcon]};
MatchWire[old] OR MatchTransistor[old] => {
TerminalIO.PutF["*** Found expression %g '%g' that is not converted automatically.\n", IO.rope[location], IO.rope[old]];
news ← CONS [old, news]};
MatchAmpersand[old]   => {
TerminalIO.PutF["*** Found expression %g '%g' that uses a variable starting with '&'.\n", IO.rope[location], IO.rope[old]];
news ← CONS [old, news]};
MatchDeclare[old]   => {
pos1: INT ← Rope.Find[old, "\""];
pos2: INT ← Rope.Find[old, "\"", pos1+1];
pos3: INT ← Rope.Find[old, "←", pos2+1];
pos4: INT ← Rope.Find[old, "]", pos3+1];
new: ROPE ← Rope.Cat[Rope.Substr[old, pos1+1, pos2-pos1-1], " ~ ", Rope.Substr[old, pos3+1, pos4-pos3-1]];
TerminalIO.PutF["changed '%g' to '%g'.\n", IO.rope[old], IO.rope[new]];
news ← CONS [new, news]};
ENDCASE  => news ← CONS [old, news];
ENDLOOP;
CDProperties.PutProp[master, Sisyph.expressionsProp, news];
IF MatchTransistor[NARROW [CDProperties.GetProp[master, $CodeFor]]] THEN TerminalIO.PutF["*** Found $CodeFor %g '%g' that cannot be converted automatically.\n", IO.rope[location], IO.rope[NARROW [CDProperties.GetProp[master, $CodeFor]]]];
IF CDProperties.GetProp[master, $CodeFor]#NIL AND CDProperties.GetProp[master, $IconFor]#NIL THEN TerminalIO.PutF["*** Found both $CodeFor and $IconFor %g. $CodeFor is probably the truth, but check that carefully!\n", IO.rope[location]];
FOR list: ROPES ← CDSatellites.GetSatelliteRopes[master], list.rest WHILE list#NIL DO
old: ROPE = list.first;
SELECT TRUE FROM
MatchName[old] OR MatchSchCI[old] OR MatchCodeCI[old] OR MatchCodeWI[old] OR MatchWire[old] OR MatchDeclare[old] OR MatchTransistor[old] OR MatchAmpersand[old] => {
needInteraction ← Rope.Cat["'", old, "' ", needInteraction]};
ENDCASE    => {};
ENDLOOP};
Convert: PROC [comm: CDSequencer.Command] = {
design: CD.Design = comm.design;
EachObj: CDDirectory.EachObjectProc = {
EachInst: CDCells.InstEnumerator = {
needInteraction ← Change[inst, Rope.Cat["in ", name]];
IF needInteraction#NIL THEN TerminalIO.PutF["*** Some instance satellite(s) in %g need to be changed: %g.\n", IO.rope[name], IO.rope[needInteraction]]};
name: ROPE ← CDDirectory.Name[me, design];
needInteraction: ROPE ← Change[me, Rope.Cat["of ", name]];
IF needInteraction#NIL THEN TerminalIO.PutF["*** Some object satellite(s) of %g need to be changed: %g.\n", IO.rope[name], IO.rope[needInteraction]];
IF NOT CDCells.IsCell[me] THEN RETURN;
[] ← CDCells.EnumerateInstances[me, EachInst]};
[] ← CDDirectory.EnumerateDesign[design, EachObj];
TerminalIO.PutF["\n*** Converted! Save the design\n"]};
NoDummiesInDir: PROC [comm: CDSequencer.Command] ~ {
Remove from directory all entries for unnamed objects and imports. Returns number of removed objects.
design: CD.Design = comm.design;
n: INT ← 0;
elem: TYPE ~ RECORD [ob: CD.Object, name: ROPE];
EachEntry: CDDirectory.EachEntryAction ~ {
IF Rope.Match[pattern: "-no name*", object: name] OR -- style 1 `unnamed' object
Rope.Match[pattern: "-noname-*", object: name] OR -- style 2 `unnamed' object
Rope.Match[pattern: "/@*", object: name] OR -- twiddled SequencingSlash
CDImports.IsImport[ob] -- Import
THEN remove ← CONS [[ob, name], remove]};
remove: LIST OF elem;
IF CDDirectory.Enumerate[design, EachEntry] THEN ERROR;
WHILE remove#NIL DO -- remove them all, check that the name/object relation is OK
n ← n+1;
IF CDDirectory.Remove[design, remove.first.name, remove.first.ob]=NIL THEN ERROR;
remove ← remove.rest;
ENDLOOP;
TerminalIO.PutF["\n%g objects made anonymous! Save the design!\n", IO.int[n]]};
Initialization
ICom: PROC[
key:  ATOM,
proc:  CDSequencer.CommandProc,
queue: CDSequencer.QueueMethod ← doQueueAndMark ] =
{CDSequencer.ImplementCommand[key, proc, NIL, queue]};
FilterSch: SinixOps.FilterProc =
{RETURN [Rope.Match["*.sch", name] OR Rope.Match["*.icon", name]]};
Convertion
CDCommandOps.RegisterWithMenu
[$Debug, "SisyphConvert", "Convert to new Sisyph syntax", $SisyphConvert, Convert, doQueueAndMark];
CDCommandOps.RegisterWithMenu
[$Debug, "Get rid of -no name-*", "Remove from directory all entries for unnamed objects and imports", $SisyphNoDummiesInDir, NoDummiesInDir, doQueueAndMark];
Filling the Layout atoms for sequences
At this point, there is a strange dependency between Sisyph and PWCore, but it is not worth the effort making a separate module
[] ← SymTab.Store[sequenceKeyWords, "Seq", NIL];
[] ← SymTab.Store[sequenceKeyWords, "SeqX", $ArrayX];
[] ← SymTab.Store[sequenceKeyWords, "SeqY", $ArrayY];
[] ← SymTab.Store[sequenceKeyWords, "RSeqX", $ReverseArrayX];
[] ← SymTab.Store[sequenceKeyWords, "RSeqY", $ReverseArrayY];
Main Menu
Sinix.RegisterExtractProc[$SisyphExtractSequence, ExtractSequence];
ICom[key: $FlushSisyphCaches, proc: FlushSisyphCaches, queue: doQueue];
SinixOps.RegisterModeCommands[mode: Sisyph.mode];
SinixOps.RegisterBackgroundExtractionCommand[CD.FetchTechnology[$cmosB], Sisyph.mode, "Sch background extraction", $SchBackgroundExtract, FilterSch]; -- only works for CMosB. Not very clean
Make Icon Menu
ICom[key: $MakeCellIcon,   proc: MakeCellIcon,   queue: doQueueAndMark];
ICom[key: $MakeWireIcon,   proc: MakeWireIcon,  queue: doQueueAndMark];
ICom[key: $MakeSequenceIcon, proc: MakeSequenceIcon, queue: doQueueAndMark];
ICom[key: $UnMakeIcon,   proc: UnMakeIcon,   queue: doQueueAndMark];
Change Visibility Menu
ICom[key: $MakeInvisibleToExtractor, proc: MakeInvisibleToExtractor,queue: doQueueAndMark];
ICom[key: $MakeVisibleToExtractor, proc: MakeVisibleToExtractor, queue: doQueueAndMark];
Make Parameter Menu (normally hidden)
ICom[key: $SisyphShowParmNames, proc: ShowParmNames, queue: doQueue];
ICom[key: $SisyphSetParmName,  proc: SetParmName];
ICom[key: $SisyphEditParmNames, proc: EditParmNames];
Expressions Menu
ICom[key: $SisyphShowInstExpressions, proc: ShowInstExpressions, queue: doQueue];
ICom[key: $SisyphAddInstExpression, proc: AddInstExpression, queue: doQueueAndMark];
ICom[key: $SisyphEditInstExpressions, proc: EditInstExpressions, queue: doQueueAndMark];
ICom[key: $SisyphShowObjExpressions, proc: ShowObjExpressions, queue: doQueue];
ICom[key: $SisyphAddObjExpression,  proc: AddObjExpression, queue: doQueueAndMark];
ICom[key: $SisyphEditObjExpressions, proc: EditObjExpressions, queue: doQueueAndMark];
END.