NewSeqIconImpl.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 September 21, 1987 1:28:28 pm PDT
Jean-Marc Frailong September 4, 1987 2:47:06 pm PDT
Last Edited by: Jacobi July 15, 1986 2:40:48 pm PDT
Jean Gastinel May 9, 1988 11:35:20 pm PDT
Don Curry November 24, 1987 5:40:35 pm PST
DIRECTORY
BrineIO, CD, CDProperties, CoreClasses, Core, CoreIO, CoreOps, CoreGeometry, CoreProperties, IO, Ports, Rope, Sinix, Sisyph, SymTab, TerminalIO;
NewSeqIconImpl: CEDAR PROGRAM
IMPORTS BrineIO, CDProperties, CoreClasses, CoreIO, CoreOps, CoreGeometry, CoreProperties, IO, Ports, Rope, Sinix, 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;
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;
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;
Since the section above will include the geometry and pins the section below (which set up links to the pins and geometry) has been commented out.
FOR i: NAT IN [0 .. sequence.public.size) DO
iconWire: Wire = CoreClasses.CorrespondingActual[iconRCT[0], subCT.public[i]];
IF iconWire=NIL THEN ERROR;
CoreGeometry.PutIndirectLazyPins[Sisyph.mode.decoration, sequence.public[i], iconWire];
CoreGeometry.PutGeometry[Sisyph.mode.decoration, sequence.public[i], CoreGeometry.GetGeometry[Sisyph.mode.decoration, iconWire]] ENDLOOP;
The object decoration!
CoreGeometry.PutObject[Sisyph.mode.decoration, sequence, obj];
We decorate with the appriopriate layout atom
CoreProperties.PutCellTypeProp[sequence, $Layout, SymTab.Fetch[sequenceKeyWords, resultVar].val]};
CopyWireProperties: PROC[from, to: Wire] = {
eachProp: PROC[atom:ATOM, ref: REF] = {CoreProperties.PutWireProp[to, atom, ref]};
CoreProperties.Enumerate[from.properties, eachProp]};
Fix to PortsImpl to save correctly the new flavor of port atoms
$PortLevelType
PortLevelTypeWrite: CoreIO.PropWriteProc ~ {
levelType: REF Ports.LevelType = NARROW[value];
BrineIO.WriteID[stream, Ports.levelTypeNames[levelType^]];
};
PortLevelTypeRead: CoreIO.PropReadProc ~ {
value ← NEW [Ports.LevelType ← Ports.FindLevelType[BrineIO.ReadID[stream]]];
};
$PortDriveType, $PortTesterDriveType
PortDriveTypeWrite: CoreIO.PropWriteProc ~ {
driveType: REF Ports.DriveType ← NARROW[value];
BrineIO.WriteID[stream, Ports.driveTypeNames[driveType^]];
};
PortDriveTypeRead: CoreIO.PropReadProc ~ {
value ← NEW [Ports.DriveType ← Ports.FindDriveType[BrineIO.ReadID[stream]]];
};
$PortDrive, $PortNewTesterDrive
PortDriveWrite: CoreIO.PropWriteProc ~ {
WITH value SELECT FROM
drive: REF Ports.Drive => {
BrineIO.WriteInt[stream, -1]; -- to indicate not a sequence ...
BrineIO.WriteID[stream, Ports.driveNames[drive^]];
};
drives: REF Ports.DriveSequence => {
BrineIO.WriteInt[stream, drives.size];
FOR i: NAT IN [0..drives.size) DO
BrineIO.WriteID[stream, Ports.driveNames[drives[i]]];
ENDLOOP;
};
ENDCASE => ERROR; -- should never happen !!!
};
PortDriveRead: CoreIO.PropReadProc ~ {
size: NAT ← BrineIO.ReadInt[stream];
IF size<0 THEN value ← NEW [Ports.Drive ← Ports.FindDrive[BrineIO.ReadID[stream]]]
ELSE { -- drive sequence
drives: Ports.DriveSequence ← NEW[Ports.DriveSequenceRec[size]];
FOR i: NAT IN [0..size) DO
drives[i] ← Ports.FindDrive[BrineIO.ReadID[stream]];
ENDLOOP;
value ← drives
};
};
Initialization
FixPortsImpl: PROC [] RETURNS [] ~ {
[] ← CoreIO.RegisterProperty[prop: $PortLevelType, write: PortLevelTypeWrite, read: PortLevelTypeRead];
[] ← CoreIO.RegisterProperty[prop: $PortDriveType, write: PortDriveTypeWrite, read: PortDriveTypeRead];
[] ← CoreIO.RegisterProperty[prop: $PortTesterDriveType, write: PortDriveTypeWrite, read: PortDriveTypeRead];
[] ← CoreIO.RegisterProperty[prop: $PortDrive, write: PortDriveWrite, read: PortDriveRead];
[] ← CoreIO.RegisterProperty[prop: $PortNewTesterDrive, write: PortDriveWrite, read: PortDriveRead];
};
Initialization
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];
FixPortsImpl[];
END.