SchImpl.mesa
Copyright © 1986 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
Don Curry April 14, 1987 1:41:03 pm PST
Jean-Marc Frailong December 17, 1986 6:20:02 pm PST
Pradeep Sindhu March 18, 1987 3:15:45 pm PST
Bertrand Serlet September 6, 1986 0:31:15 am PDT
DIRECTORY CD, CDDirectory, Convert, Core, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, Ports, PWCore, Rope, Rosemary, Sinix, Sisyph, Sch, TerminalIO, TilingClass;
SchImpl: CEDAR PROGRAM
IMPORTS CDDirectory, Convert, CoreCreate, CoreOps, CoreGeometry, CoreProperties, IO, PWCore, Rope, Sinix, Sisyph, TerminalIO, TilingClass
EXPORTS Sch
= BEGIN OPEN Sch;
iconRope: ROPE ← ".icon";
schRope: ROPE ← ".sch";
Sch: PUBLIC PROC [cx: Context, name: ROPE] = {
CheckObjectName[cx, Rope.Cat[name, schRope]];
Sisyph.Eval[cx, "coreProps ← CoreProperties.PutProp[coreProps, $PWCoreSourceDesign, design]"];
};
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 ← CDDirectory.Name[Sisyph.GetCDObj[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 ← CDDirectory.Name[Sisyph.GetCDObj[cx]];
baseCell: Core.CellType ← Sisyph.ExtractSchematicByName[objectName, cx];
ct ← PWCore.RotateCellType[baseCell, atom];
Sisyph.Eval[cx, "coreProps ← NIL"];
};
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[CDDirectory.Name[Sisyph.GetCDObj[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.PANIL;
[] ← 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.Eval[cx, "coreProps ← NIL"]; -- To prevent coreProps of the object from overriding
};
CSeq: PUBLIC PROC [cx: Sisyph.Context, count: NAT, dir: XorY] RETURNS [ct: Core.CellType] = {
ct ← CSeqOb[CDDirectory.Name[Sisyph.GetCDObj[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];
[] ← 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.Eval[cx, "coreProps ← NIL"]; -- To prevent coreProps of the object from overriding
};
CStitch: PUBLIC PROC [cx: Context, count: NAT, dir: XorY] RETURNS [ct: CellType] = {
ct ← CStitchOb[CDDirectory.Name[Sisyph.GetCDObj[cx]], cx, count, dir];
};
CStitchOb: PUBLIC PROC [obName: ROPE, cx: Context, count: NAT, dir: XorY] RETURNS [ct: CellType] = {
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;
Making a copy is important for not sharing with baseCT (crashes when doing layout)
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;
Making a copy is important for not sharing with baseCT (crashes when doing layout)
ct ← TilingClass.CreateTiling[CoreOps.CopyWire[public], tileArray, TilingClass.SchematicsNeighborX, TilingClass.SchematicsNeighborY, Rope.Cat[obName, ".StitchY"]];
};
WSeq: PUBLIC PROC [name: ROPENIL, 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.Eval[cx, "coreInstProps ← CoreProperties.PutProp[coreInstProps, $PortData,
NEW[Ports.PortDataRec ← [
levelType: initType,
driveType: aggregate,
drive: initDrive,
drives: NIL]]]"];
};
TSize: PUBLIC PROC [cx: Context, size: Rosemary.TransistorSize] = {
Sisyph.Eval[cx, "coreInstProps ← CoreProperties.PutProp[coreInstProps, $RoseTransistorSize,
NEW[Ports.Drive ← size]]"];
};
SetWire: PUBLIC PROC [cx: Context, level: Ports.Level ← L, size: Rosemary.WireSize ← charge] = {
Sisyph.Eval[cx, "coreInstProps ← CoreProperties.PutProp[coreInstProps, $RoseWireData,
NEW[Rosemary.RoseWireDataRec ← [level, size]]]"];
};
Internal Utilities
IsGlobal: PROC [w: Wire, cx: Sisyph.Context] RETURNS [BOOLFALSE] = {
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.