EU2RegsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier June 19, 1986 4:43:22 pm PDT
Barth, April 22, 1986 12:27:26 pm PST
Bertrand Serlet November 7, 1986 5:04:57 pm PST
DIRECTORY CD, CDSimpleRules, CMosB, CoreCreate, CoreOps, CoreProperties, CoreGeometry, EU2LeafUtils, EU2Regs, EU2Utils, LayoutCheckpoint, PWCore, PWCoreRoute, PWObjects, Rope;
EU2RegsImpl: CEDAR PROGRAM
IMPORTS CD, CDSimpleRules, CMosB, CoreCreate, CoreOps, CoreProperties, CoreGeometry, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PWCore, PWCoreRoute, PWObjects, Rope
EXPORTS EU2Regs =
BEGIN OPEN CoreCreate, EU2LeafUtils, EU2Regs, EU2Utils;
l: INT = CMosB.cmosB.lambda;
dpPitch: INT = 140*l;
Should be changed whenever the pitch of the DataPath changes!
-- 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] ~ {
geometry: LIST OF PWObjects.PlacedObject ← NIL;
name: ROPE ← CoreOps.GetFullWireName[cellType.public, wire];
leftWire: Wire ← CoreCreate.FindWire[leftCT.public, name];
SELECT TRUE FROM
leftWire=NIL => geometry ← LIST [
[CDSimpleRules.Rect[[4*l, sizeY], CMosB.met2], [FindBusPosX[name], 0]]];
NOT IsVBus[name, reg] => {
-- control line or contact on this bus, i.e. pins found on the right side of leftCT
DrawHoriz: CoreGeometry.EachPinProc = {
IF side=right AND layer=CMosB.met THEN geometry ← CONS [
[CDSimpleRules.Rect[[sizeX, max-min], CMosB.met], [0, min]], geometry];
};
[] ← CoreGeometry.EnumerateSides[PWCore.extractMode.decoration, leftCT, leftWire, DrawHoriz];
};
ENDCASE => {
contact on this bus
DrawContact: CoreGeometry.EachPinProc = {
IF side#right THEN RETURN;
IF layer#CMosB.met THEN RETURN;
geometry ← CONS [
[CDSimpleRules.Rect[[posX, max-min], CMosB.met], [0, min]],
geometry];
geometry ← CONS [
[CDSimpleRules.Contact[CMosB.met, CMosB.met2], [posX, min]],
geometry];
y1 ← MIN [y1, min]; y2 ← MAX [y2, max];
};
posX: INT ← FindBusPosX[name];
y1: INTIF IsTopBus[name, reg] THEN LAST[INT] ELSE 0;
y2: INTIF IsBotBus[name, reg] THEN FIRST[INT] ELSE sizeY;
[] ← CoreGeometry.EnumerateSides[PWCore.extractMode.decoration, leftCT, leftWire, DrawContact];
geometry ← CONS [
[CDSimpleRules.Rect[[4*l, y2-y1], CMosB.met2], [posX, y1]], geometry];
};
nodes ← CONS [PWObjects.CreateNode[geometry, LIST [[key: $InstanceName, val: name]]], nodes];
};
leftCT: CellType ← NARROW [CoreProperties.GetCellTypeProp[cellType, $LeftCellType]];
leftSize: CD.Position ← CD.InterestSize[PWCore.Layout[leftCT]];
sizeX: INT ← dpPitch-leftSize.x;
sizeY: INT ← leftSize.y;
reg: NATNARROW [CoreProperties.GetCellTypeProp[cellType, $Reg], REF NAT]^;
nodes: LIST OF PWObjects.Node ← NIL;
CoreOps.VisitRootAtomics[cellType.public, DrawNet];
obj ← PWObjects.CreateRouting[[0, 0, sizeX, sizeY], nodes];
};
-- 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 ← Seq["shRegIn", 32];
shRegOut: Wire ← Seq["shRegOut", 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
]];
[] ← CoreOps.SetShortWireName[In[31], "shIn"];
[] ← CoreOps.SetShortWireName[Out[0], "shOut"];
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.DecorateValue];
END.