EU2RegsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier June 14, 1986 5:24:09 pm PDT
Barth, April 22, 1986 12:27:26 pm PST
Bertrand Serlet May 12, 1986 0:47:30 am PDT
DIRECTORY CD, CDCells, CDSimpleRules, CDSymbolicObjects, CMosB, CoreCreate, CoreOps, CoreProperties, EU2LeafUtils, EU2Regs, EU2Utils, LayoutCheckpoint, PW, PWCore, PWCoreRoute, Rope;
EU2RegsImpl: CEDAR PROGRAM
IMPORTS CD, CDCells, CDSimpleRules, CDSymbolicObjects, CMosB, CoreCreate, CoreOps, CoreProperties, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PW, PWCore, PWCoreRoute, Rope
EXPORTS EU2Regs =
BEGIN OPEN CoreCreate, EU2LeafUtils, EU2Regs, EU2Utils;
-- All the buses used as input or output, including the bus for debugging (dReadBus)
ConnectedBuses: PROC [reg: PipeRange] RETURNS [buses: Wire] ~ {
dReadBusPresent: BOOLFALSE;
names: LIST OF WRNIL;
name: ROPE;
FOR i: NAT IN [0..sources[reg].sizeSel) DO
input: SourceRange ← sources[reg].inputs[i];
name ← sources[input].name;  -- name of one input
IF Rope.Equal[name, dReadBus] THEN dReadBusPresent ← TRUE;
names ← CONS[sources[input].name, names];
ENDLOOP;
-- no bus is both an input and an output
name ← sources[reg].name; -- name of the output of the source
names ← CONS[name, names];
IF Rope.Equal[name, dReadBus] THEN dReadBusPresent ← TRUE;
-- add the dReadBus if not yet present
IF ~dReadBusPresent THEN names ← CONS[dReadBus, names];
buses ← WireList[names];
};
CreateBuses: PROC [reg: PipeRange, leftCT: CellType, horizontalWire: Wire] RETURNS [cellType: CellType] ~ {
public: Wire ← CoreOps.CopyWire[Union[AllBuses[reg], horizontalWire]]; -- do not forget the copy wire! (otherwise, wires are shared and that might result in 815!!!)
cellType ← Cell[
name: "CreateBuses",
public: public,
instances: NIL
];
PWCore.SetLayout[cellType, $CreateBusesLayout, $LeftCellType, leftCT];
CoreProperties.PutCellTypeProp[cellType, $Reg, NEW[NAT ← reg]];
};
FindBusPosX: PROC [name: ROPE] RETURNS [INT] ~ {
FOR i: SourceRange IN SourceRange DO
IF sources[i].name=name THEN RETURN[(sources[i].trackPosX*8+2)*CMosB.lambda];
ENDLOOP;
ERROR; -- who the hell is this bus???
};
IsTopBus: PROC [name: ROPE, reg: NAT] RETURNS [BOOLFALSE] ~ {
FOR l: Buses ← sources[reg].topOnlyBuses, l.rest WHILE l#NIL DO
IF Rope.Equal[sources[l.first].name, name] THEN RETURN [TRUE];
ENDLOOP;
};
IsBotBus: PROC [name: ROPE, reg: NAT] RETURNS [BOOLFALSE] ~ {
FOR l: Buses ← sources[reg].botOnlyBuses, l.rest WHILE l#NIL DO
IF Rope.Equal[sources[l.first].name, name] THEN RETURN [TRUE];
ENDLOOP;
};
IsVBus: PROC [name: ROPE, reg: NAT] RETURNS [BOOLFALSE] ~ {
FOR l: Buses ← sources[reg].throughBuses, l.rest WHILE l#NIL DO
IF Rope.Equal[sources[l.first].name, name] THEN RETURN [TRUE];
ENDLOOP;
FOR l: Buses ← sources[reg].topOnlyBuses, l.rest WHILE l#NIL DO
IF Rope.Equal[sources[l.first].name, name] THEN RETURN [TRUE];
ENDLOOP;
FOR l: Buses ← sources[reg].botOnlyBuses, l.rest WHILE l#NIL DO
IF Rope.Equal[sources[l.first].name, name] THEN RETURN [TRUE];
ENDLOOP;
};
CreateBusesLayout: PWCore.LayoutProc = {
DrawNet: PROC [wire: Wire] ~ {
leftWire: Wire;
shortName: ROPE ← CoreOps.GetFullWireName[cellType.public, wire];
leftWire ← CoreCreate.FindWire[leftCT.public, shortName];
IF leftWire=NIL THEN { -- vertical through bus, no contact
posX: INT ← FindBusPosX[shortName];
inst: CD.Instance ← PW.IncludeInCell[obj,
CDSymbolicObjects.CreatePin[[4*CMosB.lambda, sizeY]],
[posX, 0]];
CDSymbolicObjects.SetName[inst, shortName];
CDSymbolicObjects.SetLayer[inst, CMosB.met2];
[] ← PW.IncludeInCell[obj,
CDSimpleRules.Rect[[4*CMosB.lambda, sizeY], CMosB.met2],
[posX, 0]];
RETURN}; 
-- control line or contact on this bus, i.e. pins found on the right side of leftCT
IF ~IsVBus[shortName, reg] THEN { -- control line
DrawHoriz: PWCore.EachPinProc = {
inst: CD.Instance;
IF side#right THEN RETURN;
IF layer#CMosB.met THEN RETURN;
inst ← PW.IncludeInCell[obj,
CDSymbolicObjects.CreatePin[[sizeX, max-min]],
[0, min]];
CDSymbolicObjects.SetName[inst, shortName];
CDSymbolicObjects.SetLayer[inst, CMosB.met];
[] ← PW.IncludeInCell[obj,
CDSimpleRules.Rect[[sizeX, max-min], CMosB.met],
[0, min]];
};
[] ← PWCore.EnumeratePins[leftCT, leftWire, DrawHoriz];
RETURN;
}
ELSE {  -- contact on this bus
DrawContact: PWCore.EachPinProc = {
inst: CD.Instance;
IF side#right THEN RETURN;
IF layer#CMosB.met THEN RETURN;
inst ← PW.IncludeInCell[obj,
CDSymbolicObjects.CreatePin[[posX, max-min]],
[0, min]];
CDSymbolicObjects.SetName[inst, shortName];
CDSymbolicObjects.SetLayer[inst, CMosB.met];
[] ← PW.IncludeInCell[obj,
CDSimpleRules.Rect[[posX, max-min], CMosB.met],
[0, min]];
[] ← PW.IncludeInCell[obj,
CDSimpleRules.Contact[CMosB.met, CMosB.met2],
[posX, min]]; -- the contact
y1 ← MIN[y1, min];
y2 ← MAX[y2, max];
};
y1, y2: INT;
posX: INT ← FindBusPosX[shortName];
y1 ← IF IsTopBus[shortName, reg] THEN LAST[INT] ELSE 0;
y2 ← IF IsBotBus[shortName, reg] THEN FIRST[INT] ELSE sizeY;
[] ← PWCore.EnumeratePins[leftCT, leftWire, DrawContact];
[] ← PW.IncludeInCell[obj, CDSimpleRules.Rect[[4*CMosB.lambda, y2-y1], CMosB.met2], [posX, y1]];
};
};
leftCT: CellType ← NARROW[CoreProperties.GetCellTypeProp[cellType, $LeftCellType]];
leftSize: CD.Position ← CD.InterestSize[PWCore.Layout[leftCT]];
sizeX: INT ← 140*CMosB.lambda-leftSize.x;
sizeY: INT ← leftSize.y;
reg: NATNARROW[CoreProperties.GetCellTypeProp[cellType, $Reg], REF NAT]^;
obj ← PW.CreateEmptyCell[];
CoreOps.VisitAtomicWires[cellType.public, DrawNet];
CDCells.SetInterestRect[obj, [0, 0, sizeX, sizeY]];
PW.RepositionCell[obj];
};
-- Assemble the reg, the muxes and the buses
-- The inputs in EU2Utils.sources[reg].inputs are in the order, i.e. for left: sel[0]->ramA
CreateRegAndMuxOnly: PROC [reg: PipeRange] RETURNS [cellType: CellType] ~ {
-- The select lines, i.e. selLeftSrc[0..3), and all public of reg, except "in"
sel: Wire ← Seq["sel", sources[reg].sizeSel+2];
-- Instances: the register and all mux transistors
mux: CellType ← Extract["RegMux.sch"]; -- Vdd, Gnd, sel, muxIn, muxOut
instances: LIST OF CellInstance ← NIL;
muxOut: Wire ← CoreOps.CreateWire[name: "muxOut"];
FOR i: NAT IN [0..sources[reg].sizeSel) DO
instances ← CONS[
Instance[mux,
["sel", Index[sel, i]],
["muxIn", sources[sources[reg].inputs[i]].name],
["muxOut", muxOut]],
instances];
ENDLOOP;
instances ← CONS[ -- sel[max] = write cBus
Instance[mux,
["sel", sel[sources[reg].sizeSel]],
["muxIn", dReadBus],
["muxOut", muxOut]],
instances];
instances ← CONS[
Instance[Extract["Register.sch"],  -- Vdd, Gnd, in, out, dRead, dOut
["in", muxOut],
["out", sources[reg].name],
["dRead", Index[sel, sources[reg].sizeSel+1]],
["dOut", dReadBus] ],
instances];
cellType ← Cell[
name: "RegAndMuxOnly",
public: Union[ConnectedBuses[reg], Wires[sel, "Vdd", "Gnd"]],
onlyInternal: Wires[muxOut],
instances: instances
];
PWCore.SetAbutY[cellType];
};
-- Same as before, but with the routing on the right
-- write from cBus (debugging only) is mapped onto sel[max+1]
-- dRead is mapped onto sel[max+2]
CreateRegCell: PROC [reg: PipeRange] RETURNS [cellType: CellType] ~ {
sel: Wire ← Seq["sel", sources[reg].sizeSel+2];
regAndMuxOnly: CellType ← CreateRegAndMuxOnly[reg];
cellType ← Cell[
name: "Reg",
public: Union[AllBuses[reg], Wires[sel, "Vdd", "Gnd"]],
instances: LIST[
Instance[regAndMuxOnly],
Instance[CreateBuses[reg, regAndMuxOnly, Wires[sel]]]]
];
PWCore.SetAbutX[cellType];
};
-- Just a replication of 32 register+mux
CreateReg: PUBLIC PROC [reg: PipeRange] RETURNS [cellType: CellType] = {
buses: Wire ← AllBuses[reg];
cellType ← SequenceCell[
name: "RegWithMux",
baseCell: CreateRegCell[reg],
count: wordSize,
sequencePorts: buses];
PWCore.SetArrayX[cellType];
};
-- Special guys
CreatePDriver: PUBLIC PROC RETURNS [cellType: CellType] = {
cellType ← SequenceCell[
name: "PDriver",
baseCell: Extract["PDriver.sch"],
count: wordSize,
sequencePorts: Wires["r2B", "st3A", "cBus", "pDriver"]];
PWCore.SetArrayX[cellType];
};
CreateCBusDriver: PUBLIC PROC RETURNS [cellType: CellType] = {
cellType ← SequenceCell[
name: "CBusDriver",
baseCell: Extract["cBusDriver.sch"],
count: wordSize,
sequencePorts: Wires["r3B", "dataIn", "cBus", "pDriver"]];
PWCore.SetArrayX[cellType];
};
CreateShRegDriver: PUBLIC PROC RETURNS [cellType: CellType] = {
cellType ← SequenceCell[
name: "shRegDriver",
baseCell: Extract["shReg.sch"],
count: wordSize,
sequencePorts: Wires["out", "ramA", "ramB", "in", "cBus", "ifuIn"]];
PWCore.SetArrayX[cellType];
};
CreatekRegAndRight: PUBLIC PROC RETURNS [cellType: CellType] = {
In: PROC [i: NAT] RETURNS [Wire] ~ {RETURN[inOut[i+1]]};
Out: PROC [i: NAT] RETURNS [Wire] ~ {RETURN[inOut[i]]};
-- To build the internal and public
Vdd: Wire ← CoreOps.CreateWire[name: "Vdd"];
Gnd: Wire ← CoreOps.CreateWire[name: "Gnd"];
ramA: Wire ← Bus["ramA"];
ramB: Wire ← Bus["ramB"];
cBus: Wire ← Bus["cBus"];
ifuIn: Wire ← Bus["ifuIn"];
kReg: Wire ← Bus["kReg"];
selKReg: Wire ← GenRegSelWire[EU2Utils.kReg];
shiftA: Wire ← CoreOps.CreateWire[name: "shiftA"];
shiftB: Wire ← CoreOps.CreateWire[name: "shiftB"];
read: Wire ← CoreOps.CreateWire[name: "read"];
write: Wire ← CoreOps.CreateWire[name: "write"];
inOut: Wire ← Seq["inOut", 33];
shRegIn: Wire ← CoreOps.CreateWires[size: 32];
shRegOut: Wire ← CoreOps.CreateWires[size: 32];
public: Wire ← WireList[LIST[Vdd, Gnd, ramA, ramB, cBus, ifuIn, kReg, selKReg, shiftA, shiftB, read, write, In[31], Out[0]]]; -- notice the indexes !!!
onlyInternal: Wire ← WireList[LIST[inOut, shRegIn, shRegOut]];
channelData: PWCoreRoute.ChannelData ← NEW[PWCoreRoute.ChannelDataRec ← [
inX: FALSE,
bottomOrLeftWires: LIST[Vdd, Gnd, kReg],
topOrRightWires: LIST[Vdd, Gnd, cBus, ifuIn, In[31], Out[0]],
trunkLayer: "metal",
branchLayer: "metal2",
wireWidthProc: PWCoreRoute.GndAndVdd25Met2MinWidth
]];
FOR i: NAT IN [0..32) DO shRegIn[i] ← In[i]; shRegOut[i] ← Out[i]; ENDLOOP;
IF EU2Utils.usekRegAndRightCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["kRegAndRight"]];
cellType ← Cell[
name: "kRegAndRight",
public: public,
onlyInternal: onlyInternal,
instances: LIST [
Instance[CreateShRegDriver[], ["in", shRegIn], ["out", shRegOut]],
Instance[CreateReg[EU2Utils.kReg], ["sel", selKReg]]
]
];
PWCore.SetLayout[cellType, $Channel, $ChannelData, channelData];
};
[] ← PWCore.RegisterLayoutAtom[$CreateBusesLayout, CreateBusesLayout, PWCore.DecorateGet];
END.