EuGenImplA.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last Edited by: Monier, July 9, 1985 4:05:06 pm PDT
DIRECTORY
CD, CDCells, CDPinObjects, CMos, Convert, EuControl, EuGen, EUtils, PW, PWCmos, PWDescr, PWPins, Rope;
EuGenImplA: CEDAR PROGRAM
IMPORTS CDCells, CMos, Convert, EuControl, EuGen, EUtils, PW, PWCmos, PWDescr, PWPins, Rope
EXPORTS EuGen =
BEGIN
OPEN EuGen;
-- Control descriptors
ramcdpd: PWDescr.Descriptor;
ramcdpu: PWDescr.Descriptor;
regscdpd: PWDescr.Descriptor;
regscdpu: PWDescr.Descriptor;
-- Here starts the layout of the RAM
RAMGen: PUBLIC PROC [design: CD.Design] RETURNS [ram: PW.ObPtr] =
BEGIN
-- This generates every row of the ram, with the appropriate decoder
RamDecFn: PW.XYFunction =
{dec: PW.ObPtr ← RamRow3Dec[y];
RETURN[IF PW.EVEN[y] THEN PW.AbutX[design, dec, ramRow]
ELSE PW.AbutX[design, PW.FlipY[design, dec], ramRowFlipped]]};
-- Generating the three decoders for each row of the RAM
RamRow3Dec: PROC [n: INT] RETURNS [row3Dec: PW.ObPtr] =
BEGIN
aDec, bDec, cDec: PW.ObPtr;
PW.Output["Row number ", Convert.RopeFromInt[n], "\n"];
PWDescr.SetInt[ramcdpd, "aAdrHi", n];
aDec ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "aAdrHi", 0, 0];
PWDescr.SetInt[ramcdpd, "bAdrHi", n];
bDec ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "bAdrHi", 0, 0];
PWDescr.SetInt[ramcdpd, "cAdrHi", n];
cDec ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "cAdrHi", 0, 0];
row3Dec ← PW.AbutX[design,
PW.AbutY[design, bDec, cDec, aDec, fillerDec], -- same order as select lines
routingDecToRam];
END;
PrechargeGen: PROC RETURNS [ramPrecharge: PW.ObPtr] =
BEGIN
PrechargeCtrlGen: PROC RETURNS [prechCtrl: PW.ObPtr] =
BEGIN
VddProc: PW.SelectNamesProc = {keepIt ← Rope.Equal[name, "vdd"]};
RenameNPhA: PWPins.RenameProc =
{SELECT TRUE FROM
Rope.Equal[oldRope, "wireLeft"] => newRope ← "nPhA";
Rope.Equal[oldRope, "wireRight"] => newRope ← NIL;
ENDCASE => newRope ← oldRope};
RenameNPhB: PWPins.RenameProc =
{SELECT TRUE FROM
Rope.Equal[oldRope, "wireLeft"] => newRope ← "nPhB";
Rope.Equal[oldRope, "wireRight"] => newRope ← "nPhB";
ENDCASE => newRope ← oldRope};
RenamePhA: PWPins.RenameProc =
{SELECT TRUE FROM
Rope.Equal[oldRope, "wireLeft"] => newRope ← "PhA";
Rope.Equal[oldRope, "wireRight"] => newRope ← NIL;
ENDCASE => newRope ← oldRope};
RenamePhB: PWPins.RenameProc =
{SELECT TRUE FROM
Rope.Equal[oldRope, "wireLeft"] => newRope ← "PhB";
Rope.Equal[oldRope, "wireRight"] => newRope ← NIL;
ENDCASE => newRope ← oldRope};
wire, vddConnect, ctrl, vddRect:PW.ObPtr;
listOb: PW.ListOb ← NIL;
size: CD.Position;
ramcdpu ← EmptyDescrRamPU[];
ramcdpd ← EmptyDescrRamPD[];
-- PhA
PWDescr.SetBit[ramcdpd, "PhA", TRUE];
wire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
PWDescr.SetBit[ramcdpd, "PhA", FALSE];
listOb ← CONS[PWPins.RenamePins[design, wire, RenamePhA], listOb];
-- nPhA
PWDescr.SetBit[ramcdpu, "nPhA", TRUE];
wire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
PWDescr.SetBit[ramcdpu, "nPhA", FALSE];
listOb ← CONS[PWPins.RenamePins[design, wire, RenameNPhA], listOb];
-- PhB
PWDescr.SetBit[ramcdpd, "PhB", TRUE];
wire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
PWDescr.SetBit[ramcdpd, "PhB", FALSE];
listOb ← CONS[PWPins.RenamePins[design, wire, RenamePhB], listOb];
-- nPhB
PWDescr.SetBit[ramcdpu, "nPhB", TRUE];
wire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
PWDescr.SetBit[ramcdpu, "nPhB", FALSE];
listOb ← CONS[PWPins.RenamePins[design, wire, RenameNPhB], listOb];
-- Bias voltage generator
PWDescr.SetBit[ramcdpu, "Vbias", TRUE];
listOb ← CONS[EuControl.BiasVoltage[design, ramcdpd, ramcdpu], listOb];
PWDescr.SetBit[ramcdpu, "Vbias", FALSE];
ctrl ← PW.AbutListY[design, listOb];
vddConnect ← EUtils.CtrlFiller[design, ctrl, contactPrechargeBitLines, VddProc];
size ← PW.Size[vddConnect];
vddRect ← PWCmos.Rect[CMos.met2, [size.x, size.y-12*l]];
PW.IncludeInCell[design, vddConnect, vddRect, [0, 12*l]]; -- hack!!!
[] ← CDCells.RepositionCell[vddConnect, design];
prechCtrl ← PW.AbutY[design, ctrl, vddConnect];
END;
listOb: PW.ListOb ← NIL;
block, prechargeBitLines, contactPrechargeBitLines, ctrl: PW.ObPtr;
-- Make one block (=1 bitslice = 4 RAM bits)
PW.Output["The precharge of the RAM", "\n"];
prechargeBitLines ← PW.Get[design, "prechargeBitLines"];
contactPrechargeBitLines ← PW.Get[design, "contactPrechargeBitLines"];
block ← PW.AbutX[design,
contactPrechargeBitLines,
PW.ArrayX[design, prechargeBitLines, nbBitsperSliceInRam]];
block ← PWPins.RenamePins[design, block];
-- Rename the kBus pins
listOb ← NIL; -- re-used
FOR i: INT IN [0..nbSlices) DO
RenameK: PWPins.RenameProc =
{IF Rope.Equal[oldRope, "kBus"] THEN newRope ← PWPins.Index[oldRope, nbSlices-1-i];
IF Rope.Equal[oldRope, "vdd"] OR Rope.Equal[oldRope, "gnd"] THEN newRope ← oldRope};
listOb ← CONS[PWPins.RenamePins[design, block, RenameK], listOb];
ENDLOOP;
-- Now add the control
ctrl ← PrechargeCtrlGen[];
ramPrecharge ← PW.AbutX[design,
ctrl,
EUtils.QadCR[design, ctrl, contactPrechargeBitLines, glueWidth, FALSE],
PW.AbutListX[design, listOb]];
END;
decConnectionPrecharge, genericDec, genericCtrl, fillerDec, routingDecToRam, contactSelectLinesAndKBus, ramRow, ramRowFlipped, ramArrayandDec: PW.ObPtr;
PW.Output["Generating the RAM", "\n"];
decConnectionPrecharge ← PW.CreateEmptyCell[];
ramcdpu ← InitDescrRamPU[];
ramcdpd ← InitDescrRamPD[];
-- Cells which will be re-used a lot
contactSelectLinesAndKBus ← PW.Get[design, "contactSelectLinesAndKBus"];
genericDec ← EuControl.Nand[design, ramcdpd, ramcdpu];
genericCtrl ← PW.AbutY[design, genericDec, PW.FlipY[design, genericDec], genericDec];
fillerDec ← EUtils.CtrlFiller[design, genericCtrl, contactSelectLinesAndKBus];
genericCtrl ← PW.AbutY[design, genericCtrl, fillerDec];
routingDecToRam ← EUtils.QadCR[design, genericCtrl, contactSelectLinesAndKBus, glueWidth];
-- One row of ram cells
ramRow ← PW.ArrayX[design,
PW.AbutX[design,
contactSelectLinesAndKBus,
PW.ArrayX[design, PW.Get[design, "threePortedRamCell"], nbBitsperSliceInRam]],
nbSlices];
ramRow ← PWPins.RenamePins[design, ramRow];
ramRowFlipped ← PW.FlipY[design, ramRow];
-- The whole ram with the decoder, generated row by row, flipping alternate rows
ramArrayandDec ← PW.MapFunctionY[design, RamDecFn, 0, nbRowsInRam];
-- Add precharge on top of the array
ram ← PW.AbutY[design,
ramArrayandDec,
PrechargeGen[]];
ram ← PWPins.RenamePins[design, ram];
PW.RenameObject[design, ram, "ram"];
END;
BitLinesMuxesGen: PUBLIC PROC [design: CD.Design] RETURNS [mux: PW.ObPtr] =
BEGIN
MuxCtrlGen: PROC [] RETURNS [muxCtrl: PW.ObPtr] =
BEGIN
a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3: PW.ObPtr;
ramcd1: PWDescr.Descriptor;
ramcd1 ← InitDescrRamPD[];
ramcdpd ← InitDescrRamPD[];
ramcdpu ← InitDescrRamPU[];
PWDescr.SetBit[ramcdpd, "nhold2BA", TRUE];
PWDescr.SetBit[ramcdpd, "nrejectBA", TRUE];
PWDescr.SetInt[ramcdpd, "aAdrLow", 0];
a0 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "aAdrLow", 1];
a1 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "aAdrLow", 2];
a2 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "aAdrLow", 3];
a3 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "aAdrLow", 0, 0];
PWDescr.SetInt[ramcdpd, "bAdrLow", 0];
b0 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "bAdrLow", 1];
b1 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "bAdrLow", 2];
b2 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "bAdrLow", 3];
b3 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "bAdrLow", 0, 0];
PWDescr.SetInt[ramcdpd, "cAdrLow", 0];
c0 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "cAdrLow", 1];
c1 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "cAdrLow", 2];
c2 ← EuControl.Nand[design, ramcdpd, ramcdpu];
PWDescr.SetInt[ramcdpd, "cAdrLow", 3];
c3 ← EuControl.Nand[design, ramcdpd, ramcdpu, TRUE];
PWDescr.SetInt[ramcdpd, "cAdrLow", 0, 0];
muxCtrl ← PW.AbutListY[design, LIST[a0, a1, a2, a3, b0, b1, b2, b3, c0, c1, c2, c3]];
END;
MuxDataGen: PROC [] RETURNS [muxDataPathSlice: PW.ObPtr] =
BEGIN
ABLFn: PW.XYFunction =
{RETURN[IF x=y THEN aBLMuxTrans ELSE bitLineMuxNoTrans]};
BBLFn: PW.XYFunction =
{RETURN[IF x=y THEN bBLMuxTrans ELSE bitLineMuxNoTrans]};
CBLFn: PW.XYFunction =
{RETURN[IF x=y THEN cBLMuxTrans ELSE bitLineMuxNoTrans]};
muxA, muxB, muxC, fourToOne, contacts: PW.ObPtr;
bitLineMuxNoTrans: PW.ObPtr ← PW.Get[design, "bitLineMuxNoTrans"];
aBLMuxTrans: PW.ObPtr ← PW.Get[design, "aBLMuxTrans"];
bBLMuxTrans: PW.ObPtr ← PW.Get[design, "bBLMuxTrans"];
cBLMuxTrans: PW.ObPtr ← PW.Get[design, "cBLMuxTrans"];
PW.Output["Bit lines multiplexers", "\n"];
-- The three sets of muxes
muxA ← PW.MapFunction[design, ABLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam];
muxB ← PW.MapFunction[design, BBLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam];
muxC ← PW.MapFunction[design, CBLFn, 0, nbBitsperSliceInRam, 0, nbBitsperSliceInRam];
-- Put together (from top to bottom, a, b and c), and add the contacts on the left
contacts ← PW.AbutY[design,
PW.Get[design, "contactFourToOne"],
PW.ArrayY[design, PW.Get[design, "contactBLMux"], 3*nbBitsperSliceInRam]];
fourToOne ← PW.AbutY[design,
PW.ArrayX[design, PW.Get[design, "fourToOneBLMuxes"], nbBitsperSliceInRam],
muxC, muxB, muxA];
muxDataPathSlice ← PW.AbutX[design, contacts, fourToOne];
END;
fillerSlice, muxDataPathSlice, ctrl, dp: PW.ObPtr;
ramcdpd ← InitDescrRamPD[];
ctrl ← MuxCtrlGen[];
muxDataPathSlice ← MuxDataGen[];
fillerSlice ← EUtils.CtrlFiller[design, muxDataPathSlice, ctrl];
dp ← PW.ArrayX[design, PW.AbutY[design, muxDataPathSlice, fillerSlice], nbSlices];
mux ← PW.AbutX[design,
ctrl,
EUtils.QadCR[design, ctrl, dp, glueWidth],
dp];
PW.RenameObject[design, mux, "mux"];
END;
BitLinesReadWriteGen: PUBLIC PROC [design: CD.Design] RETURNS [readWrite: PW.ObPtr] =
BEGIN
ReadWriteCtrlGen: PROC [] RETURNS [readWriteCtrl: PW.ObPtr] =
BEGIN
nPhBWire, phAWire, inverters: PW.ObPtr;
ramcdpd ← EmptyDescrRamPD[];
ramcdpu ← EmptyDescrRamPU[];
-- nPhB wire
PWDescr.SetBit[ramcdpu, "nPhB", TRUE];
nPhBWire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
nPhBWire ← PWPins.RenamePins[design, nPhBWire, RenameNPhB];
PWDescr.SetBit[ramcdpu, "nPhB", FALSE];
-- PhA wire: no hold, since the muxes take care of it
PWDescr.SetBit[ramcdpd, "PhA", TRUE];
phAWire ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
phAWire ← PWPins.RenamePins[design, phAWire, RenamePhA];
PWDescr.SetBit[ramcdpd, "PhA", FALSE];
-- The 3*8 inverters computing the complement of the RAM address
ramcdpd ← EmptyDescrRamPD[];
ramcdpu ← EmptyDescrRamPU[];
PWDescr.SetInt[ramcdpd, "aAdrHi", PWDescr.allOnes];
PWDescr.SetInt[ramcdpd, "aAdrLow", PWDescr.allOnes];
PWDescr.SetInt[ramcdpd, "bAdrHi", PWDescr.allOnes];
PWDescr.SetInt[ramcdpd, "bAdrLow", PWDescr.allOnes];
PWDescr.SetInt[ramcdpd, "cAdrHi", PWDescr.allOnes];
PWDescr.SetInt[ramcdpd, "cAdrLow", PWDescr.allOnes];
inverters ← EuControl.Inverters[design, ramcdpd, ramcdpu, TRUE];
readWriteCtrl ← PW.AbutY[design, phAWire, nPhBWire, inverters];
END;
ReadWriteDataGen: PROC [] RETURNS [readWriteDataPath: PW.ObPtr] =
BEGIN
bitLinesRead, bitLinesWrite, readWrite: PW.ObPtr;
bitLinesRead ← PW.Get[design, "bitLinesRead"];
bitLinesWrite ← PW.Get[design, "bitLinesWrite"];
readWrite ← PW.AbutY[design, bitLinesWrite, bitLinesRead];
readWriteDataPath ← PW.ArrayX[design, readWrite, nbSlices];
END;
PW.Output["Read and write ports of the RAM", "\n"];
readWrite ← EUtils.Assemble[design, ReadWriteCtrlGen[], ReadWriteDataGen[]];
PW.RenameObject[design, readWrite, "readWrite"];
END;
DrivekBusGen: PUBLIC PROC [design: CD.Design] RETURNS [cell: PW.ObPtr] =
BEGIN
cAdrGreaterThan239: PW.ObPtr;
PW.Output["kBus driver", "\n"];
ramcdpd ← InitDescrRamPD[];
ramcdpu ← InitDescrRamPU[];
PWDescr.SetInt[ramcdpd, "cAdrHi", 60, 60]; -- cAdr>239, i.e. cAdr=1111xxxx
PWDescr.SetBit[ramcdpd, "nhold2BA", TRUE];
cAdrGreaterThan239 ← EuControl.Nand[design, ramcdpd, ramcdpu];
cell ← EUtils.MakeTstDriver[design: design, in: "c", out: "kOut", ctrlListOb: LIST[cAdrGreaterThan239]];
PW.RenameObject[design, cell, "kBusDriver"];
END;
AdrRegGen: PUBLIC PROC [design: CD.Design] RETURNS [regs: PW.ObPtr] =
BEGIN
ctrl: PW.ObPtr;
regD: EUtils.RegDescr;
PW.Output["Address registers", "\n"];
-- Bringing PhB to the address register
ramcdpd ← EmptyDescrRamPD[];
ramcdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[ramcdpd, "PhB", TRUE];
ctrl ← EuControl.RouteTo[design, ramcdpd, ramcdpu];
ctrl ← PWPins.RenamePins[design, ctrl, RenamePhB];
-- The address register is a regular register
regD ← NEW[EUtils.RegDescrRec ← [
inListOb: LIST["k"],
out: "down",
ctrlListOb: LIST[ctrl]]];
regs ← PW.AbutY[design,
RoutingAdrRegGen[design],
EUtils.MakeReg[design, regD]];
PW.RenameObject[design, regs, "addressRegisters"];
END;
RoutingAdrRegGen: PROC [design: CD.Design] RETURNS [routing: PW.ObPtr] =
BEGIN
RoutingCtrlGen: PROC RETURNS [ctAdr: PW.ObPtr] =
BEGIN
listOb: PW.ListOb ← NIL;
IntToWires: PROC [name: ROPE, nbBits: INT] =
BEGIN
ramcdpd ← EmptyDescrRamPD[];
PWDescr.SetInt[ramcdpd, name, PWDescr.allOnes];
FOR i: INT DECREASING IN [0..nbBits) DO
PWDescr.SetInt[ramcdpd, name, PW.TwoToThe[i], PW.TwoToThe[i]];
listOb ← CONS[EuControl.RouteTo[design, ramcdpd, ramcdpu], listOb];
ENDLOOP;
PWDescr.SetInt[ramcdpd, name, 0, 0];
END;
ramcdpd ← EmptyDescrRamPD[];
ramcdpu ← EmptyDescrRamPU[];
-- Connecting the address wires
IntToWires["aAdrHi", 6];
IntToWires["aAdrLow", 2];
IntToWires["bAdrHi", 6];
IntToWires["bAdrLow", 2];
IntToWires["cAdrHi", 6];
IntToWires["cAdrLow", 2];
-- Now the gap between the RAM control part and the rest (mask=> pass) (except bit)
-- Notice the change in descriptor
regscdpd ← EmptyDescrRegsPD[];
PWDescr.SetBit[regscdpd, "PhA", TRUE];
PWDescr.SetBit[regscdpd, "PhB", TRUE];
PWDescr.SetBit[regscdpd, "nhold2BA", TRUE];
PWDescr.SetBit[regscdpd, "nrejectBA", TRUE];
PWDescr.SetBit[regscdpd, "DExecute", TRUE];
PWDescr.SetInt[regscdpd, "DStateAddress", PWDescr.allOnes];
regscdpu ← InitDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhA", TRUE];
listOb ← CONS[EuControl.Gap[design, regscdpd, regscdpu], listOb];
-- And the connection of the 8 remaining wires to the bottom (add the inverters somewhere!!!)
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 2, 2];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 1, 1];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", 0, 0];
PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 2, 2];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 1, 1];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", 0, 0];
PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 2, 2];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 1, 1];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", 0, 0];
PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", TRUE];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", FALSE, FALSE];
PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", TRUE];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", FALSE, FALSE];
ctAdr ← PW.AbutListY[design, listOb];
END;
WiringFn24: PW.XYFunction =
{RETURN[SELECT TRUE FROM
x=23-y => wiresCt,
x<23-y => wiresNothing, -- below
ENDCASE => wiresNoCt]}; -- above
WiringFn8: PW.XYFunction =
{RETURN[SELECT TRUE FROM
x=31-y => wiresCt,
x<31-y => wiresNothing, -- below
ENDCASE => wiresNoCt]}; -- above
routingAdrRegToCtrlPass, routingAdrRegToCtrlNoPass, wires, gapWires, glue, ctrl: PW.ObPtr;
wiresCt: PW.ObPtr ← PW.Get[design, "routingAdrRegToCtrl"];
wiresNoCt: PW.ObPtr ← PW.Inst[design, wiresCt, LIST["Contact"]];
wiresNothing: PW.ObPtr ← PW.Inst[design, wiresCt, LIST["Contact", "wire"]];
routingAdrRegToCtrlPass ← PW.Get[design, "routingAdrRegToCtrlPass"];
routingAdrRegToCtrlNoPass ← PW.Inst[design, routingAdrRegToCtrlPass, LIST["vertical"]];
PW.Output["A lot of routing for the addresses", "\n"];
gapWires ← PW.AbutX[design,
PW.ArrayX[design, routingAdrRegToCtrlNoPass, 24],
PW.ArrayX[design, routingAdrRegToCtrlPass, 8]];
wires ← PW.AbutY[design,
PW.MapFunction[design, WiringFn8, 0, nbSlices, 0, 8],
gapWires,
PW.MapFunction[design, WiringFn24, 0, nbSlices, 0, 24]];
ctrl ← RoutingCtrlGen[];
glue ← EUtils.QadCR[design, ctrl, wires, glueWidth];
routing ← PW.AbutX[design, ctrl, glue, wires];
PW.RenameObject[design, routing, "addressRegisters"];
END;
-- The registers providing the field descriptor
FDRegsGen: PUBLIC PROC [design: CD.Design] RETURNS [fdRegs: PW.ObPtr] =
BEGIN
Regs: PROC RETURNS [regs: PW.ObPtr] =
BEGIN
regD: EUtils.RegDescr;
listOb: PW.ListOb ← NIL;
genericCtrl, ctrl, kBusAB, field, fd, dp: PW.ObPtr;
-- The 4 inverters for DStateAddress, 8 inverters for EUAluLeftSrc1BA, EUAluRightSrc1BA, EUStore2ASrc1BA, EUSt3AisCBus2BA and EURes3AisCBus2BA, then 13 inverters for the fd, 5 for EUAluOp2AB, 1 for EUWriteToPBus3AB, and 1 for EURes3BisPBus3AB
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRegsPU[];
PWDescr.SetInt[regscdpd, "DStateAddress", PWDescr.allOnes];
PWDescr.SetInt[regscdpd, "EUAluLeftSrc1BA", PWDescr.allOnes];
PWDescr.SetInt[regscdpd, "EUAluRightSrc1BA", PWDescr.allOnes];
PWDescr.SetInt[regscdpd, "EUStore2ASrc1BA", PWDescr.allOnes];
PWDescr.SetBool[regscdpd, "EUSt3AisCBus2BA", TRUE];
PWDescr.SetBool[regscdpd, "EURes3AisCBus2BA", TRUE];
PWDescr.SetBool[regscdpd, "FDInsert", TRUE];
PWDescr.SetInt[regscdpd, "FDMask", PWDescr.allOnes];
PWDescr.SetInt[regscdpd, "FDShift", PWDescr.allOnes];
PWDescr.SetInt[regscdpd, "EUAluOp2AB", PWDescr.allOnes];
PWDescr.SetBool[regscdpd, "EUWriteToPBus3AB", TRUE];
PWDescr.SetBool[regscdpd, "EURes3BisPBus3AB", TRUE];
listOb ← CONS[EuControl.Inverters[design, regscdpd, regscdpu, TRUE], listOb];
-- The 2 nand decoders for fd
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhB", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhA", TRUE];
PWDescr.SetInt[regscdpd, "EUAluOp2AB", fop]; -- EUAluOp2AB=FOP
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, "EUAluOp2AB", fopk]; -- EUAluOp2AB=FOPK
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb];
PWDescr.SetInt[regscdpd, "EUAluOp2AB", 0, 0]; -- clean-up
-- The 2 nand decoders for field and kBusAB (reject???)
-- just PhA.nrejectBA for kBusAB
PWDescr.SetBit[regscdpd, "nrejectBA", TRUE];
PWDescr.SetBit[regscdpd, "nhold2BA", TRUE];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb];
PWDescr.SetBit[regscdpd, "EULoadField3BA", TRUE]; -- for field
genericCtrl ← EuControl.Nand[design, regscdpd, regscdpu, TRUE];
listOb ← CONS[genericCtrl, listOb];
PWDescr.SetBit[regscdpd, "nrejectBA", FALSE];
PWDescr.SetBit[regscdpd, "nhold2BA", FALSE];
ctrl ← PW.AbutListY[design, listOb];
-- Generate the three registers
regD ← NEW[EUtils.RegDescrRec ← [inListOb: LIST["k"], out: "opL"]];
kBusAB ← EUtils.MakeRegDP[design, regD];
regD ← NEW[EUtils.RegDescrRec ← [inListOb: LIST["c"], out: "opR", interruptBuses: LIST["opLBus", "opRBus", "downBus"]]];
field ← EUtils.MakeRegDP[design, regD];
regD ← NEW[EUtils.RegDescrRec ← [inListOb: LIST["opL", "opR"], out: "down"]];
fd ← EUtils.MakeRegDP[design, regD];
dp ← PW.AbutY[design, field, kBusAB, fd];
regs ← EUtils.Assemble[design, ctrl, dp];
END;
Routing: PROC RETURNS [routing: PW.ObPtr] =
BEGIN
WiringFn13: PW.XYFunction =
{RETURN[SELECT TRUE FROM
x<3 => wiresNothing,
x=15-y => wiresCt,
x>15-y => wiresNothing,
ENDCASE => wiresNoCt]};
Ctrl: PROC RETURNS [ctrl: PW.ObPtr] =
BEGIN
IntToWires: PROC [name: ROPE, nbBits: INT] =
BEGIN
regscdpd ← EmptyDescrRegsPD[];
PWDescr.SetInt[regscdpd, name, PWDescr.allOnes];
FOR i: INT DECREASING IN [0..nbBits) DO
PWDescr.SetInt[regscdpd, name, PW.TwoToThe[i], PW.TwoToThe[i]];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
ENDLOOP;
PWDescr.SetInt[regscdpd, name, 0, 0];
END;
listOb: PW.ListOb ← NIL;
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRegsPU[];
-- insert
PWDescr.SetBool[regscdpd, "FDInsert", TRUE];
listOb ← CONS[EuControl.RouteTo[design, regscdpd, regscdpu], listOb];
-- mask
IntToWires["FDMask", 6];
-- shift
IntToWires["FDShift", 6];
ctrl ← PW.AbutListY[design, listOb];
END;
wires: PW.ObPtr ← PW.MapFunction[design, WiringFn13, 0, nbSlices, 0, 13];
routing ← EUtils.Assemble[design,
Ctrl[],
wires];
END;
wiresCt: PW.ObPtr ← PW.Get[design, "routingfdRegsToCtrl"];
wiresNoCt: PW.ObPtr ← PW.Inst[design, wiresCt, LIST["Contact"]];
wiresNothing: PW.ObPtr ← PW.Inst[design, wiresCt, LIST["Contact", "wire"]];
PW.Output["Registers associated with the Field Unit", "\n"];
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRegsPU[];
PWDescr.SetBit[regscdpu, "nPhB", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhA", TRUE];
PWDescr.SetBit[regscdpd, "nhold2BA", TRUE];
PWDescr.SetBit[regscdpd, "nrejectBA", TRUE];
fdRegs ← PW.AbutY[design, Regs[], Routing[]];
PW.RenameObject[design, fdRegs, "fdRegisters"];
END;
-- Let's shift to the layout of the Field Unit
FieldUnitGen: PUBLIC PROC [design: CD.Design] RETURNS [fieldUnit: PW.ObPtr] =
BEGIN
MaskGen: PROC[maskNb: INT] RETURNS [mask: PW.ObPtr] =
BEGIN
MaskCtrlGen: PROC [maskNb: INT] RETURNS [maskCtrl: PW.ObPtr] =
BEGIN
ctrl: PW.ObPtr;
listOb: PW.ListOb ← NIL;
name: ROPE = IF maskNb=1 THEN "FDShift" ELSE "FDMask";
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhA", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhB", TRUE];
-- I want to isolate the ith bit of FDShift
PWDescr.SetInt[regscdpd, name, 0, 1];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb];
PWDescr.SetInt[regscdpd, name, 0, 2];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, name, 4, 4];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb];
PWDescr.SetInt[regscdpd, name, 0, 8];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb];
PWDescr.SetInt[regscdpd, name, 16, 16];
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb];
PWDescr.SetInt[regscdpd, name, 0, 32];
ctrl ← EuControl.Nand[design, regscdpd, regscdpu];
listOb ← CONS[ctrl, listOb];
maskCtrl ← PW.AbutListY[design, listOb];
END;
MaskGate: PROC [i, b: INT] RETURNS [PW.ObPtr] =
BEGIN
useNand: BOOL ← ~PW.XthBitOfN[b, i];
IF PW.ODD[b] THEN useNand ← ~useNand;
IF useNand THEN RETURN[maskNandArray[b]] ELSE RETURN[maskNorArray[b]];
END;
MaskFn: PW.XYFunction = 
{RETURN[ PW.AbutListX[design,
LIST[IF PW.EVEN[x] THEN maskBusesSel ELSE maskBusesOne,
MaskGate[x, 1],
MaskGate[x, 2],
MaskGate[x, 3],
MaskGate[x, 4],
MaskGate[x, 5],
IF maskNb=1 THEN maskRight1 ELSE maskRight2]]]};
maskNor, maskNand, maskBuses, maskBusesOne, maskBusesSel, maskRight, maskRight1, maskRight2: PW.ObPtr;
maskNorArray, maskNandArray: ARRAY [1..5] OF PW.ObPtr;
maskNor ← PW.Get[design, "maskNor"];
maskNand ← PW.Get[design, "maskNand"];
maskBuses ← PW.Get[design, "maskBuses"];
maskRight ← PW.Get[design, "maskRight"];
maskNorArray[1] ← PW.Inst[design, maskNor, LIST["Ct1"], FALSE];
maskNorArray[2] ← PW.Inst[design, maskNor, LIST["Ct2"], FALSE];
maskNorArray[3] ← PW.Inst[design, maskNor, LIST["Ct3"], FALSE];
maskNorArray[4] ← PW.Inst[design, maskNor, LIST["Ct4"], FALSE];
maskNorArray[5] ← PW.Inst[design, maskNor, LIST["Ct5"], FALSE];
maskNandArray[1] ← PW.Inst[design, maskNand, LIST["Ct1"], FALSE];
maskNandArray[2] ← PW.Inst[design, maskNand, LIST["Ct2"], FALSE];
maskNandArray[3] ← PW.Inst[design, maskNand, LIST["Ct3"], FALSE];
maskNandArray[4] ← PW.Inst[design, maskNand, LIST["Ct4"], FALSE];
maskNandArray[5] ← PW.Inst[design, maskNand, LIST["Ct5"], FALSE];
maskBusesOne ← PW.Inst[design, maskBuses, LIST["One"], FALSE];
maskBusesSel ← PW.Inst[design, maskBuses, LIST["Sel"], FALSE];
maskRight1 ← PW.Inst[design, maskRight, LIST["mask1"], FALSE];
maskRight2 ← PW.Inst[design, maskRight, LIST["mask2"], FALSE];
mask ← EUtils.Assemble[design,
MaskCtrlGen[maskNb],
PW.MapFunctionX[design, MaskFn, 0, nbSlices]];
END;
ShifterGen: PROC RETURNS [shifter: PW.ObPtr] =
BEGIN
CtrlGen: PROC RETURNS [ctrl: PW.ObPtr] =
BEGIN
listOb: PW.ListOb ← NIL;
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhA", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhB", TRUE];
FOR i: INT IN [0..nbSlices+1) DO
PWDescr.SetInt[regscdpd, "FDShift", i]; -- shift=i
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, PW.ODD[i]], listOb];
ENDLOOP;
ctrl ← PW.AbutListY[design, listOb];
END;
shifter0Cell, shifterCell, shifter32Cell, ctrl, sh: PW.ObPtr;
shifter0Cell ← PW.Get[design, "shifter0Cell"];
shifterCell ← PW.Get[design, "shifterCell"];
shifter32Cell ← PW.Get[design, "shifter32Cell"];
sh ← PW.AbutY[design,
PW.ArrayX[design, shifter32Cell, nbSlices],
PW.Array[design, shifterCell, nbSlices, nbSlices-1],
PW.ArrayX[design, shifter0Cell, nbSlices]];
ctrl ← CtrlGen[];
shifter ← EUtils.Assemble[design, ctrl, sh];
END;
MergeGen: PROC RETURNS [merge: PW.ObPtr] =
BEGIN
CtrlGen: PROC RETURNS [ctrl: PW.ObPtr] =
BEGIN
generic: PW.ObPtr;
regscdpd2: PWDescr.Descriptor;
listOb: PW.ListOb ← NIL;
regscdpd ← EmptyDescrRegsPD[];
regscdpd2 ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhA", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhB", TRUE];
PWDescr.SetBit[regscdpd2, "PhB", TRUE];
generic ← EuControl.Nand[design, regscdpd, regscdpu];
-- EUAluOp2AB=FOP OR EUAluOp2AB=FOPK (could be checked on one bit)
PWDescr.SetInt[regscdpd, "EUAluOp2AB", fop]; -- EUAluOp2AB=FOP
PWDescr.SetInt[regscdpd2, "EUAluOp2AB", fopk]; -- EUAluOp2AB=FOPK
listOb ← CONS[EuControl.NorOfNands[design, LIST[regscdpd, regscdpd2], regscdpu], listOb];
regscdpd ← EmptyDescrRegsPD[];
regscdpu ← EmptyDescrRamPU[];
PWDescr.SetBit[regscdpu, "nPhA", TRUE];
PWDescr.SetBit[regscdpu, "Vbias", TRUE];
PWDescr.SetBit[regscdpd, "PhB", TRUE];
PWDescr.SetBool[regscdpd, "FDInsert", TRUE]; -- insert
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu], listOb];
PWDescr.SetBool[regscdpd, "FDInsert", FALSE]; -- ~insert
listOb ← CONS[EuControl.Nand[design, regscdpd, regscdpu, TRUE], listOb];
ctrl ← PW.AbutListY[design, listOb];
END;
ctrl, mergeDp: PW.ObPtr;
mergeDp ← PW.ArrayX[design, PW.Get[design, "fuMerge"], nbSlices];
ctrl ← CtrlGen[];
merge ← EUtils.Assemble[design, ctrl, mergeDp];
END;
PW.Output["The Field Unit", "\n"];
fieldUnit ← PW.AbutY[design,
MaskGen[1],
PW.FlipY[design, MaskGen[2]],
MergeGen[],
ShifterGen[]
];
PW.RenameObject[design, fieldUnit, "fieldUnit"];
END;
END.