SchImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Louis Monier February 13, 1986 3:46:07 pm PST
Barth, February 18, 1987 11:08:39 pm PST
Last Edited by: Louis Monier January 22, 1987 10:48:47 pm PST
Jean-Marc Frailong December 17, 1986 6:20:02 pm PST
Pradeep Sindhu June 26, 1987 2:02:27 pm PDT
Bertrand Serlet April 24, 1987 2:37:49 pm PDT
DIRECTORY CD, Convert, Core, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, Ports, PWCore, Rope, Rosemary, Sinix, Sisyph, Sch, TerminalIO, TilingClass;
SchImpl:
CEDAR
PROGRAM
IMPORTS Convert, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, PWCore, Rope, Sinix, Sisyph, TerminalIO, TilingClass
EXPORTS Sch
= BEGIN OPEN Sch;
iconRope: ROPE ← ".icon";
schRope: ROPE ← ".sch";
Name:
PROC [cx: Context]
RETURNS [name:
ROPE] = {
RETURN [Sisyph.mode.nameProc[Sisyph.GetCDObj[cx], cx]];
};
Sch:
PUBLIC
PROC [cx: Context, name:
ROPE] = {
CheckObjectName[cx, Rope.Cat[name, schRope]];
Sisyph.AddProp[cx, $PWCoreSourceDesign, "design", FALSE];
};
Icon:
PUBLIC
PROC [cx: Context, name:
ROPE]
RETURNS [ct: CellType] = {
CheckObjectName[cx, Rope.Cat[name, iconRope]];
ct ← Sisyph.ExtractSchematicByName[Rope.Cat[name, schRope], cx];
};
CheckObjectName:
PUBLIC
PROC [cx: Context, assertedName:
ROPE] = {
objectName: ROPE ← Name[cx];
IF NOT Rope.Equal[objectName, assertedName] THEN TerminalIO.PutF["Warning: ChipNDale directory name %g does not correspond to asserted name %g", IO.refAny[objectName], IO.refAny[assertedName]];
};
Orient:
PUBLIC
PROC [cx: Context, atom:
ATOM]
RETURNS [ct: CellType] = {
objectName: ROPE ← Name[cx];
baseCell: Core.CellType ← Sisyph.ExtractSchematicByName[objectName, cx];
ct ← PWCore.RotateCellType[baseCell, atom];
Sisyph.Store[cx, Sisyph.corePropsRope, NEW [Core.Properties ← NIL]]; -- ??? I do not understand that one [BS, April 24, 1987 2:35:53 pm PDT]
};
WireSide:
PROC [wire: Core.Wire, baseCT: Core.CellType]
RETURNS [sides: CoreGeometry.Sides ← CoreGeometry.noSide] ~ {
Finds the sides on which wire touches baseCT (of which it is a public). CoreGeometry.noSide will be returned if the wire has no pins. This should be in CoreGeometry.
EachPin: CoreGeometry.EachPinProc = {
sides[side] ← TRUE;
};
[] ← CoreGeometry.EnumerateSides[Sisyph.mode.decoration, baseCT, wire, EachPin];
};
WireSideProblem:
PROC [wire: Core.Wire, msg:
ROPE, baseCT: Core.CellType] ~ {
TerminalIO.PutF["\n*** Wire %g %g in cell %g\n",
IO.rope[CoreOps.GetFullWireName[baseCT.public, wire]],
IO.rope[msg],
IO.rope[CoreOps.GetCellTypeName[baseCT]]];
SIGNAL Sinix.CallerBug[];
};
CSeqStitch:
PUBLIC
PROC [cx: Sisyph.Context, count:
NAT, dir: XorY]
RETURNS [ct: Core.CellType] = {
ct ← CSeqStitchOb[Name[cx], cx, count, dir];
};
CSeqStitchOb:
PROC [obName:
ROPE, cx: Sisyph.Context, count:
NAT, dir: XorY]
RETURNS [ct: Core.CellType] = {
sWires, fsWires: LIST OF CoreCreate.WR;
EachWire: CoreOps.EachWireProc = {
sides: CoreGeometry.Sides = WireSide[wire, baseCT];
vertical: BOOL = sides[top] OR sides[bottom];
horizontal: BOOL = sides[left] OR sides[right];
IF ~(vertical OR horizontal) THEN RETURN; -- This wire has no pins, try its sons
IF vertical AND horizontal THEN WireSideProblem[wire, "touches adjacent sides", baseCT];
IF (horizontal
AND (dir=X
OR dir=
RX))
OR (vertical
AND (dir=Y
OR dir=
RY))
THEN {
wireName: Rope.ROPE ← CoreOps.GetShortWireName[wire];
inWire: BOOL ← Rope.Match["*In", wireName];
IF inWire
OR Rope.Match["*Out", wireName]
THEN {
this: BOOL ← sides[left] OR sides[bottom];
searchName: Rope.ROPE ← Rope.Cat[Rope.Substr[wireName, 0, Rope.Length[wireName] - (IF inWire THEN Rope.Length["In"] ELSE Rope.Length["Out"])], IF inWire THEN "Out" ELSE "In"];
IF (sides[top] AND sides[bottom]) OR (sides[left] AND sides[right]) THEN WireSideProblem[wire, "touches both sides but is a stitch", baseCT];
FOR pas:
LIST
OF CoreCreate.
PA ← stitchPorts, pas.rest
UNTIL pas=
NIL
DO
IF Rope.Equal[
NARROW[
IF this
THEN pas.first.actual
ELSE pas.first.public], searchName]
THEN {
IF this THEN pas.first.public ← wireName ELSE pas.first.actual ← wireName;
EXIT;
};
REPEAT FINISHED => stitchPorts ← CONS[IF this THEN [wireName, NIL] ELSE [NIL, wireName], stitchPorts];
ENDLOOP;
}
};
IF (vertical AND (dir=X OR dir=RX)) OR (horizontal AND (dir=Y OR dir=RY)) THEN IF wire.size=0 THEN sWires ← CONS[wire, sWires] ELSE fsWires ← CONS[wire, fsWires];
subWires ← FALSE;
};
baseCT: Core.CellType ← Sisyph.ExtractSchematicByName[obName, cx];
stitchPorts: LIST OF CoreCreate.PA ← NIL;
IF count=0 THEN RETURN[NIL];
[] ← CoreOps.VisitWireSeq[baseCT.public, EachWire];
ct ← CoreCreate.SequenceCell[
name: Rope.Cat[obName, "Seq",
SELECT dir
FROM
X => "X", Y => "Y", RX => "RX", RY => "RY", ENDCASE => ERROR],
baseCell: baseCT,
count: count,
sequencePorts: CoreCreate.WireList[sWires],
flatSequencePorts: CoreCreate.WireList[fsWires],
stitchPorts: stitchPorts];
SELECT dir
FROM
X => PWCore.SetArrayX[ct];
Y => PWCore.SetArrayY[ct];
RX => PWCore.SetLayout[ct, $ReverseArrayX];
RY => PWCore.SetLayout[ct, $ReverseArrayY];
ENDCASE => ERROR;
Sisyph.Store[cx, Sisyph.corePropsRope, NEW [Core.Properties ← NIL]]; -- To prevent coreProps of the object from overriding (??? No comprendo [BS April 24, 1987 2:36:38 pm PDT])
};
CSeq:
PUBLIC
PROC [cx: Sisyph.Context, count:
NAT, dir: XorY]
RETURNS [ct: Core.CellType] = {
ct ← CSeqOb[Name[cx], cx, count, dir];
};
CSeqOb:
PUBLIC
PROC [obName:
ROPE, cx: Sisyph.Context, count:
NAT, dir: XorY]
RETURNS [ct: Core.CellType] = {
sWires, fsWires: LIST OF CoreCreate.WR;
EachWire: CoreOps.EachWireProc = {
sides: CoreGeometry.Sides = WireSide[wire, baseCT];
vertical: BOOL = sides[top] OR sides[bottom];
horizontal: BOOL = sides[left] OR sides[right];
IF ~(vertical OR horizontal) THEN RETURN; -- This wire has no pins, try its sons
IF vertical AND horizontal THEN WireSideProblem[wire, "touches adjacent sides", baseCT];
IF (vertical AND (dir=X OR dir=RX)) OR (horizontal AND (dir=Y OR dir=RY)) THEN IF wire.size=0 THEN sWires ← CONS[wire, sWires] ELSE fsWires ← CONS[wire, fsWires];
subWires ← FALSE;
};
baseCT: Core.CellType ← Sisyph.ExtractSchematicByName[obName, cx];
IF count=0 THEN RETURN[NIL];
[] ← CoreOps.VisitWireSeq[baseCT.public, EachWire];
ct ← CoreCreate.SequenceCell[
name: Rope.Cat[obName, "Seq",
SELECT dir
FROM
X => "X", Y => "Y", RX => "RX", RY => "RY", ENDCASE => ERROR],
baseCell: baseCT,
count: count,
sequencePorts: CoreCreate.WireList[sWires],
flatSequencePorts: CoreCreate.WireList[fsWires]
];
SELECT dir
FROM
X => PWCore.SetArrayX[ct];
Y => PWCore.SetArrayY[ct];
RX => PWCore.SetLayout[ct, $ReverseArrayX];
RY => PWCore.SetLayout[ct, $ReverseArrayY];
ENDCASE => ERROR;
Sisyph.Store[cx, Sisyph.corePropsRope, NEW [Core.Properties ← NIL]]; -- To prevent coreProps of the object from overriding (??? I do not understand that [BS, April 24, 1987 2:33:34 pm PDT])
};
CStitch:
PUBLIC
PROC [cx: Context, count:
NAT, dir: XorY]
RETURNS [ct: CellType] = {
ct ← CStitchOb[Name[cx], cx, count, dir];
};
CStitchOb:
PUBLIC
PROC [obName:
ROPE, cx: Context, count:
NAT, dir: XorY]
RETURNS [ct: CellType] = {
IF count=0 THEN RETURN[NIL];
SELECT dir
FROM
X => ct ← StitchX[obName, cx, count];
Y => ct ← StitchY[obName, cx, count];
ENDCASE => ERROR;
Sisyph.Store[cx, Sisyph.corePropsRope, NEW [Core.Properties ← CoreProperties.Props[[$Layout, CoreProperties.GetCellTypeProp[ct, $Layout]]]]];
};
StitchX:
PROC [obName:
ROPE, cx: Sisyph.Context, count:
NAT]
RETURNS [ct: CellType] ~ {
public: Wire;
tileRow: TilingClass.TileRow ← NEW [TilingClass.TileRowRec[count]];
tileArray: TilingClass.TileArray ← NEW [TilingClass.TileArrayRec[1]];
baseCT: CellType ← Sisyph.ExtractSchematicByName[obName, cx];
publicElements, arrayedWires, leftSideOnlyWires, rightSideOnlyWires, globalWires: Wires ← NIL;
EachWire: CoreOps.EachWireProc = {
sides: CoreGeometry.Sides = WireSide[wire, baseCT];
vertical: BOOL = sides[top] OR sides[bottom];
IF vertical AND (sides[right] OR sides[left]) THEN WireSideProblem[wire, "touches adjacent sides", baseCT];
IF vertical
THEN {
newPublic: Wire ← CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]];
arrayedWires ← CONS[wire, arrayedWires];
FOR i:
INT
IN [0..count)
DO
newPublic[i] ← CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL];
ENDLOOP;
publicElements ← CONS[newPublic, publicElements];
}
ELSE {
IF sides=CoreGeometry.noSide
THEN {
IF IsGlobal[wire, cx]
THEN {
globalWires ← CONS [wire, globalWires];
publicElements ← CONS [wire, publicElements]
}
}
ELSE {
IF sides[left] THEN leftSideOnlyWires ← CONS[wire, leftSideOnlyWires];
IF sides[right] THEN rightSideOnlyWires ← CONS[wire, rightSideOnlyWires];
publicElements ← CONS [wire, publicElements]
}
}
};
[] ← CoreOps.VisitWireSeq[baseCT.public, EachWire];
public ← CoreOps.CreateWire[publicElements];
FOR i:
INT
IN [0..count)
DO
tileRow[i] ← NEW [TilingClass.TileRec ← [type: baseCT]]
ENDLOOP;
FOR wl: Wires ← leftSideOnlyWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileRow[0].renaming ← CONS[[wireName, wireName], tileRow[0].renaming];
ENDLOOP;
FOR wl: Wires ← rightSideOnlyWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileRow[count-1].renaming ← CONS[[wireName, wireName], tileRow[count-1].renaming];
ENDLOOP;
FOR wl: Wires ← globalWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i:
NAT
IN [0..count)
DO
tileRow[i].renaming ← CONS[[wireName, wireName], tileRow[i].renaming];
ENDLOOP;
ENDLOOP;
FOR wl: Wires ← arrayedWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i:
NAT
IN [0..count)
DO
tileRow[i].renaming ← CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileRow[i].renaming];
ENDLOOP;
ENDLOOP;
tileArray[0] ← tileRow;
Copying the public is necessary to avoid sharing of wires between cellTypes
ct ← TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[obName, ".StitchX"]];
};
StitchY:
PROC [obName:
ROPE, cx: Sisyph.Context, count:
NAT]
RETURNS [ct: CellType] ~ {
public: Wire;
tileArray: TilingClass.TileArray ← NEW [TilingClass.TileArrayRec[count]];
baseCT: CellType ← Sisyph.ExtractSchematicByName[obName, cx];
publicElements, arrayedWires, botSideOnlyWires, topSideOnlyWires, globalWires: Wires ← NIL;
EachWire: CoreOps.EachWireProc = {
sides: CoreGeometry.Sides = WireSide[wire, baseCT];
horizontal: BOOL = sides[left] OR sides[right];
IF horizontal AND (sides[top] OR sides[bottom]) THEN WireSideProblem[wire, "touches adjacent sides", baseCT];
IF horizontal
THEN {
newPublic: Wire ← CoreOps.CreateWires[count, CoreOps.GetShortWireName[wire]];
arrayedWires ← CONS[wire, arrayedWires];
FOR i:
INT
IN [0..count)
DO
newPublic[i] ← CoreOps.SetShortWireName[CoreOps.CopyWire[wire], NIL];
ENDLOOP;
publicElements ← CONS[newPublic, publicElements];
}
ELSE {
IF sides=CoreGeometry.noSide
THEN {
IF IsGlobal[wire, cx]
THEN {
globalWires ← CONS [wire, globalWires];
publicElements ← CONS [wire, publicElements]
}
}
ELSE {
IF sides[bottom] THEN botSideOnlyWires ← CONS[wire, botSideOnlyWires];
IF sides[top] THEN topSideOnlyWires ← CONS[wire, topSideOnlyWires];
publicElements ← CONS [wire, publicElements]
}
}
};
[] ← CoreOps.VisitWireSeq[baseCT.public, EachWire];
public ← CoreOps.CreateWire[publicElements];
FOR i:
INT
IN [0..count)
DO
tileArray[i] ← NEW [TilingClass.TileRowRec[1]];
tileArray[i][0] ← NEW [TilingClass.TileRec ← [type: baseCT]]
ENDLOOP;
FOR wl: Wires ← botSideOnlyWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileArray[0][0].renaming ← CONS[[wireName, wireName], tileArray[0][0].renaming];
ENDLOOP;
FOR wl: Wires ← topSideOnlyWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
tileArray[count-1][0].renaming ← CONS[[wireName, wireName], tileArray[count-1][0].renaming];
ENDLOOP;
FOR wl: Wires ← globalWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i:
NAT
IN [0..count)
DO
tileArray[i][0].renaming ← CONS[[wireName, wireName], tileArray[i][0].renaming];
ENDLOOP;
ENDLOOP;
FOR wl: Wires ← arrayedWires, wl.rest
WHILE wl#
NIL
DO
wireName: ROPE ← CoreOps.GetShortWireName[wl.first];
FOR i:
NAT
IN [0..count)
DO
tileArray[i][0].renaming ← CONS[[wireName, Rope.Cat[wireName, "[", Convert.RopeFromInt[i], "]"]], tileArray[i][0].renaming];
ENDLOOP;
ENDLOOP;
Copying the public is necessary to avoid sharing of wires between cellTypes
ct ← TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[obName, ".StitchY"]];
};
WSeq:
PUBLIC
PROC [name:
ROPE ←
NIL, size:
NAT]
RETURNS [wire: Wire] = {
wire ← CoreCreate.Seq[name, size];
};
WRange:
PUBLIC
PROC [name:
ROPE, start:
NAT, size:
NAT]
RETURNS [wire: Core.Wire] = {
wire ← CoreCreate.Seq[size: size];
FOR i:
NAT
IN [0..size)
DO
[] ← CoreOps.SetShortWireName[wire[i], IO.PutFR["%g[%g]", IO.rope[name], IO.int[start+i]]];
ENDLOOP;
};
WIndex:
PUBLIC
PROC [name:
ROPE, index:
NAT]
RETURNS [wire: Core.Wire] = {
wire ← CoreOps.CreateWire[name: name];
[] ← CoreOps.SetShortWireName[wire, IO.PutFR["%g[%g]", IO.rope[name], IO.int[index]]];
};
InitPort:
PUBLIC
PROC [cx: Context, initType: Ports.LevelType ← b, initDrive: Ports.Drive ← none] = {
Sisyph.Store[cx, "initType", NEW [Ports.LevelType ← initType]];
Sisyph.Store[cx, "initDrive", NEW [Ports.Drive ← initDrive]];
Sisyph.AddProp[
cx, $PortData,
"NEW[Ports.PortDataRec ← [levelType: initType, driveType: aggregate, drive: initDrive, drives: NIL]]",
TRUE];
};
TSize:
PUBLIC
PROC [cx: Context, size: Rosemary.TransistorSize] = {
Sisyph.Store[cx, "size", NEW [Rosemary.TransistorSize ← size]];
Sisyph.AddProp[cx, $RoseTransistorSize, "NEW[Ports.Drive ← size]", TRUE];
};
SetWire:
PUBLIC
PROC [cx: Context, level: Ports.Level ← L, size: Rosemary.WireSize ← charge] = {
Sisyph.Store[cx, "level", NEW [Ports.Level ← level]];
Sisyph.Store[cx, "size", NEW [Rosemary.WireSize ← size]];
Sisyph.AddProp[cx, $RoseWireData, "NEW[Rosemary.RoseWireDataRec ← [level, size]]", TRUE];
};
Internal Utilities
IsGlobal:
PROC [w: Wire, cx: Sisyph.Context]
RETURNS [
BOOL ←
FALSE] = {
name: ROPE ← CoreOps.GetShortWireName[w];
FOR lr:
LIST
OF
ROPE ← Sisyph.GetGlobalNames[cx], lr.rest
WHILE lr#
NIL
DO
IF Rope.Equal[name, lr.first] THEN RETURN [TRUE]
ENDLOOP;
};
END.