MCImpl:
CEDAR
PROGRAM
IMPORTS CD, CDOrient, CDCells, CDPinObjects, CDProperties, CMos, Convert, TerminalIO, PWCmos, PWPins, PW, Rope
EXPORTS MC =
BEGIN
l: INT = CD.lambda;
nLines: PUBLIC INT ← 32;
nCamColumns: PUBLIC INT ← 20;
nRamColumns: PUBLIC INT ← 44;
nEntriesPerLine: PUBLIC INT ← 4;
VddRingWidth: PUBLIC INT ← 100*l;
GndRingWidth: PUBLIC INT ← 100*l;
CellToIR:
PUBLIC
PROC [cellpos:
CD.Position, obj:
CD.ObPtr]
RETURNS [irpos:
CD.Position] = {
ir: CD.Rect ← CD.InterestRect[obj];
irpos ← [cellpos.x-ir.x1, cellpos.y-ir.y1];
};
IRToCell:
PUBLIC
PROC [irpos:
CD.Position, obj:
CD.ObPtr]
RETURNS [cellpos:
CD.Position] = {
ir: CD.Rect ← CD.InterestRect[obj];
cellpos ← [irpos.x+ir.x1, irpos.y+ir.y1];
};
SelectAll: PUBLIC MC.SelectPinProc = {sel ← TRUE};
IndexedName:
PUBLIC
PROC [name: Rope.
ROPE, index:
INT]
RETURNS [Rope.
ROPE] = {
RETURN[Rope.Cat[name, "[", Convert.RopeFromInt[index], "]"]];
};
TTYOut:
PUBLIC PROC [r1, r2, r3, r4, r5, r6: Rope.
ROPE ←
NIL] = {
TerminalIO.WriteRope[Rope.Cat[r1, r2, r3, r4, r5, r6]];
};
CreateFillerCell:
PUBLIC
PROC [design:
CD.Design, size:
CD.Position]
RETURNS [result:
PW.ObPtr] = {
result ← PW.CreateEmptyCell[];
CDCells.SetInterestRect[result, [0, 0, size.x, size.y]];
PW.IncludeInCell[design,
result,
CDPinObjects.CreatePinOb[[2, 2]],
[size.x/2, size.y/2]];
PW.IncludeInDirectory[design, result, "FillerCell"];
};
TopFillerCell:
PUBLIC
PROC [design:
CD.Design, obj:
PW.ObPtr, fillDist:
INT, selectPinProc:
MC.SelectPinProc ← SelectAll]
RETURNS [result:
PW.ObPtr] = {
objIR: CD.Rect ← CD.InterestRect[obj];
resultPtr: CD.CellPtr;
ProcessEdgePin: PWPins.AppEnumerator = {
side: PWPins.Side ← PWPins.GetSide[obj, app].side;
newPin: CD.ApplicationPtr;
IF side=PWPins.top
AND selectPinProc[app]
THEN {
pinSize: CD.Position ← CDOrient.OrientedSize[app.ob.size, app.orientation];
Put down the rectangle
PW.IncludeInCell[design,
result,
PWCmos.Rect[CDPinObjects.GetLayer[app],
[pinSize.x, fillDist]], -- size
[app.location.x-objIR.x1, 0]]; -- location
Put down a pin at the end of it
newPin ←
NEW[
CD.Application ← [
ob: CDPinObjects.CreatePinOb[app.ob.size],
location: [app.location.x-objIR.x1, fillDist-pinSize.y], orientation: app.orientation,
properties: CDProperties.CopyProps[app.properties]]];
CDPinObjects.SetName[newPin, CDPinObjects.GetName[app]];
resultPtr.contents ← CONS[newPin, resultPtr.contents];
};
};
IF fillDist<=0 THEN ERROR;
result ← PW.CreateEmptyCell[]; resultPtr ← NARROW[result.specificRef];
CDCells.SetInterestRect[result, [0, 0, objIR.x2-objIR.x1, fillDist]];
[] ← PWPins.EnumerateEdgePins[obj, ProcessEdgePin];
PW.IncludeInDirectory[design, result, "Filler"];
result ← PWPins.RenamePins[design, result];
};
LeftFillerCell:
PUBLIC
PROC [design:
CD.Design, obj:
PW.ObPtr, fillDist:
INT, selectPinProc:
MC.SelectPinProc ← SelectAll]
RETURNS [result:
PW.ObPtr] = {
RETURN[PW.Rot90[design, TopFillerCell[design, PW.Rot270[design, obj], fillDist, selectPinProc]]];
};
RightFillerCell:
PUBLIC
PROC [design:
CD.Design, obj:
PW.ObPtr, fillDist:
INT, selectPinProc:
MC.SelectPinProc ← SelectAll]
RETURNS [result:
PW.ObPtr] = {
RETURN[PW.Rot270[design, TopFillerCell[design, PW.Rot90[design, obj], fillDist, selectPinProc]]];
};
MakeBusX:
PUBLIC
PROC [design:
CD.Design, layer:
CD.Layer, names:
LIST
OF Rope.
ROPE, wireLength, wireThickness, wireSeparation:
INT]
RETURNS [result:
PW.ObPtr] = {
resultPtr: CD.CellPtr;
nWires: INT ← 0;
IF wireLength<=0 OR wireThickness<=0 THEN ERROR;
result ← PW.CreateEmptyCell[]; resultPtr ← NARROW[result.specificRef];
FOR l:
LIST
OF Rope.
ROPE ← names, l.rest
UNTIL l=
NIL
DO
leftPin, rightPin: CD.ApplicationPtr;
wireLocation: CD.Position ← [0, wireSeparation+nWires*(wireThickness+wireSeparation)];
PW.IncludeInCell[design,
result,
PWCmos.Rect[layer, [wireLength, wireThickness]],
wireLocation];
Put pins at both ends
leftPin ←
NEW[
CD.Application ← [
ob: CDPinObjects.CreatePinOb[[2, wireThickness]],
location: wireLocation, orientation: CDOrient.original]];
rightPin ←
NEW[
CD.Application ← [
ob: CDPinObjects.CreatePinOb[[2, wireThickness]],
location: [wireLength-2, wireLocation.y], orientation: CDOrient.original]];
CDPinObjects.SetName[leftPin, l.first];
CDPinObjects.SetName[rightPin, l.first];
CDPinObjects.SetLayer[leftPin, layer];
CDPinObjects.SetLayer[rightPin, layer];
resultPtr.contents ← CONS[leftPin, resultPtr.contents];
resultPtr.contents ← CONS[rightPin, resultPtr.contents];
nWires ← nWires+1;
ENDLOOP;
CDCells.SetInterestRect[result, [0, 0, wireLength, wireSeparation+nWires*(wireThickness+wireSeparation)]];
PW.IncludeInDirectory[design, result, "Bus"];
};
MakeBusY:
PUBLIC
PROC [design:
CD.Design, layer:
CD.Layer, names:
LIST
OF Rope.
ROPE, wireLength, wireThickness, wireSeparation:
INT]
RETURNS [result:
PW.ObPtr] = {
result ← PW.Rot270[design, MakeBusX[design, layer, names, wireLength, wireThickness, wireSeparation]];
};
ConnectTopToBus:
PUBLIC
PROC [design:
CD.Design, obj:
PW.ObPtr, bus:
PW.ObPtr]
RETURNS[result:
PW.ObPtr] = {
objIR: CD.Rect ← CD.InterestRect[obj];
busIR: CD.Rect ← CD.InterestRect[bus];
resultIR: CD.Rect ← [0, 0, objIR.x2-objIR.x1, busIR.y2-busIR.y1];
ProcessObjPin: PWPins.AppEnumerator = {
[app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE]
side: PWPins.Side ← PWPins.GetSide[obj, app].side;
objPinName: Rope.ROPE ← CDPinObjects.GetName[app];
objPinLayer: CD.Layer ← CDPinObjects.GetLayer[app];
busPin: CD.ApplicationPtr ← NIL;
SetBusPin: PWPins.AppEnumerator = {
[app: CD.ApplicationPtr] RETURNS [quit: BOOL ← FALSE]
side: PWPins.Side ← PWPins.GetSide[bus, app].side;
IF Rope.Equal[CDPinObjects.GetName[app], objPinName]
AND side=PWPins.left
THEN busPin ← app;
};
IF side=PWPins.top
THEN {
appSize: CD.Position ← CDOrient.OrientedSize[app.ob.size, app.orientation];
busPinSize: CD.Position;
Set the global variable busPin corresponding to this obj pin - yuck!
[] ← PWPins.EnumerateEdgePins[bus, SetBusPin];
IF busPin=
NIL
THEN {
TTYOut["\n** MCImpl Warning: pin named """, objPinName, """ not found."];
TTYOut[" MCImpl: ", objPinName, " "];
RETURN;
};
busPinSize ← CDOrient.OrientedSize[busPin.ob.size, busPin.orientation];
Put down rectangle
PW.IncludeInCell[design,
result,
PWCmos.Rect[CDPinObjects.GetLayer[app],
[appSize.x, busPin.location.y+busPinSize.y-busIR.y1]], -- size
[app.location.x-objIR.x1, 0]]; -- location
Put down contact
PW.IncludeInCell[design,
result,
PWCmos.Contact[CMos.met, CMos.met2],
[app.location.x-objIR.x1-2, busPin.location.y-busIR.y1]];
};
};
result ← PW.CreateEmptyCell[];
CDCells.SetInterestRect[result, resultIR];
[] ← PWPins.EnumerateEdgePins[obj, ProcessObjPin];
PW.IncludeInDirectory[design, result, "ExtensionTopToBus"];
};
ConnectBotToBus:
PUBLIC PROC [design:
CD.Design, obj:
PW.ObPtr, bus:
PW.ObPtr]
RETURNS[result:
PW.ObPtr] = {
result ← PW.FlipY[design, ConnectTopToBus[design, PW.FlipY[design, obj], PW.FlipY[design, bus]]];
};
ConnectRightToBus:
PUBLIC PROC [design:
CD.Design, obj:
PW.ObPtr, bus:
PW.ObPtr]
RETURNS[result:
PW.ObPtr] = {
result ← PW.Rot270[design, ConnectTopToBus[design, PW.Rot90[design, obj], PW.Rot90[design, bus]]];
};
ConnectLeftToBus:
PUBLIC PROC [design:
CD.Design, obj:
PW.ObPtr, bus:
PW.ObPtr]
RETURNS[result:
PW.ObPtr] = {
result ← PW.Rot90[design, ConnectTopToBus[design, PW.Rot270[design, obj], PW.Rot270[design, bus]]];
};
END.