EuControlImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Louis Monier, May 10, 1985 10:46:58 pm PDT
Last Edited by: Monier, July 8, 1985 4:29:40 pm PDT
DIRECTORY
CD, Convert, EuControl, PW, PWDescr, Rope, SymTab;
EuControlImpl: CEDAR PROGRAM
IMPORTS Convert, PW, PWDescr, Rope, SymTab
EXPORTS EuControl =
BEGIN OPEN EuControl;
--User-level routines for describing control in this style of design: nand precharged decoder
-- Integers and bools are represented by pairs of wires, bits (not bools) on a single wire
ControlProc: TYPE = PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [obj: PW.ObPtr];
-- A generic proc that turns a descriptor into some part of the control
ControlLine: PROC [design: CD.Design,
descrPD, descrPU: PWDescr.Descriptor,
DescrToPD, DescrToPU: ControlProc,
gnd, sep, driver: PW.ObPtr,
name: ROPE,
flipY: BOOLFALSE] RETURNS [controlLine: PW.ObPtr] =
BEGIN
controlLine ← PW.AbutX[design,
gnd,
DescrToPD[design, descrPD],
sep,
DescrToPU[design, descrPU],
driver];
IF flipY THEN controlLine ← PW.FlipY[design, controlLine];
PW.RenameObject[design, controlLine, "name"];
END;
-- Assemble pieces into a NAND decoder
Nand: PUBLIC PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor, flipY: BOOLFALSE] RETURNS [nandDec: PW.ObPtr] =
{nandDec ← ControlLine[design, descrPD, descrPU, DescrToNandPD, DescrToNandPU, decGround, decNPSep, decDriver, "nandDec", flipY]};
-- A wire or set of wires routing a particular item to the datapath (right side)
RouteTo: PUBLIC PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor] RETURNS [wire: PW.ObPtr] =
{wire ← ControlLine[design, descrPD, descrPU, DescrToWirePD, DescrToWirePU, decWireGround, decWireNPSep, decWireDriver, "wire"]};
-- Bias voltage generator
BiasVoltage: PUBLIC PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor] RETURNS [bias: PW.ObPtr] =
{bias ← ControlLine[design, descrPD, descrPU, DescrToWirePD, DescrToWirePU, decWireGround, decWireNPSep, decBiasVoltage, "biasVoltage"]};
-- A set of inverters computing the complementary of signals specified by the descriptor
Inverters: PUBLIC PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor, flipY: BOOLFALSE] RETURNS [inverters: PW.ObPtr] =
{inverters ← ControlLine[design, descrPD, descrPU, DescrToInvPD, DescrToInvPU, decInvGround, devInvNPSep, decInvDriver, "inverters", flipY]};
-- A separations between two control parts having different descriptors of the same size; the semantic is the same as the routing, but specifies whether a wire is interrupted or not; if metal2 is used to double poly, this is the place to contact both layers
Gap: PUBLIC PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor, flipY: BOOLFALSE] RETURNS [gap: PW.ObPtr] =
{gap ← ControlLine[design, descrPD, descrPU, DescrToGapPD, DescrToGapPU, decGapGround, decGapNPSep, decGapDriver, "gap", flipY]};
-- A set of NAND decoders, grouped as pull-downs of a precharged NOR; each branch has a different pull-down descriptor, but there is only one pull-up descriptor
NorOfNands: PUBLIC PROC [design: CD.Design, listDescrPD: LIST OF PWDescr.Descriptor, descrPU: PWDescr.Descriptor, flipY: BOOLFALSE] RETURNS [norDec: PW.ObPtr] =
BEGIN
flipBranch: BOOLTRUE;
listBranch: PW.ListOb ← CONS[Nand[design, listDescrPD.first, descrPU]];
FOR l: LIST OF PWDescr.Descriptor ← listDescrPD.rest, l.rest WHILE l#NIL DO
listBranch ← CONS[NorBranch[design, l.first, descrPU, flipBranch], listBranch];
flipBranch ← ~flipBranch;
ENDLOOP;
norDec ← PW.AbutListY[design, listBranch];
IF flipY THEN norDec ← PW.FlipY[design, norDec];
PW.RenameObject[design, norDec, "norDec"];
END;
NorBranch: PROC [design: CD.Design, descrPD, descrPU: PWDescr.Descriptor, flipY: BOOLFALSE] RETURNS [branch: PW.ObPtr] =
{branch ← ControlLine[design, descrPD, descrPU, DescrToNandPD, DescrToNandPU, decGround, decNPSep, IF flipY THEN norDecAttachDown ELSE norDecAttachUp, "branch", flipY]};
-- Internal routines for generating control
-- Descriptor to pull-down chain
DescrToNandPD: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [obj: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
BoolToPD: PROC [bool: PWDescr.BoolRef] RETURNS [obj: PW.ObPtr] =
{obj ← SELECT TRUE FROM
~bool.val0 AND ~bool.val1 => decX,
bool.val0 AND ~bool.val1 => decOne,
~bool.val0 AND bool.val1 => decZero,
ENDCASE => ERROR}; -- both bits=1 has no meaning here
IntToPD: PROC [int: PWDescr.IntRef] RETURNS [obj: PW.ObPtr] =
BEGIN
found: BOOL;
ref: SymTab.Val; 
-- check the order of bits
IntToObj: PW.XYFunction = {RETURN[BoolToPD[int.bools[x]]]};
uniqueID: INT ← int.nbBits+100*int.val+10000*int.mask;
key: ROPE ← Rope.Concat["PD", Convert.RopeFromInt[uniqueID]];
[found, ref] ← SymTab.Fetch[cellCache, key];
IF ~found THEN {
obj ← PW.MapFunctionX[design, IntToObj, 0, int.nbBits];
[] ← SymTab.Store[cellCache, key, obj];}
ELSE obj ← NARROW[ref];
END;
forEachItem: PWDescr.ForEachItemProc =
{obj: PW.ObPtr ←
WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => obj ← IF bit.val THEN decTransistor ELSE decNoTransistor,
bool: PWDescr.BoolRef => obj ← BoolToPD[bool],
int: PWDescr.IntRef => obj ← IntToPD[int],
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];};
PWDescr.EnumerateItems[descr, forEachItem];
obj ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- Descriptor to pull-up chain: different from DescrToPD because not only the cells, but also the assembly process is different (flip)
DescrToNandPU: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [obj: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
forEachItem: PWDescr.ForEachItemProc =
{obj: PW.ObPtr ←
WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => obj ←
IF bit.val THEN (IF flip THEN decPTransFlip ELSE decPTrans)
ELSE (IF flip THEN decPNoTransFlip ELSE decPNoTrans),
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];
flip ← ~flip;};
flip: BOOLFALSE;
PWDescr.EnumerateItems[descr, forEachItem];
obj ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- Descriptor to wire routing to a particular item in the descriptor: only one bit is wired.
DescrToWirePD: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [wire: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
BoolToWire: PROC [bool: PWDescr.BoolRef] RETURNS [obj: PW.ObPtr] =
{obj ← SELECT TRUE FROM
~bool.val0 AND ~bool.val1 => decWireX,
bool.val0 AND ~bool.val1 => decWireZeroCt,
~bool.val0 AND bool.val1 => decWireOneCt,
ENDCASE => ERROR};
IntToWire: PROC [int: PWDescr.IntRef] RETURNS [obj: PW.ObPtr] =
BEGIN
found: BOOL;
ref: SymTab.Val; 
IntToAdrFn: PW.XYFunction = {RETURN[BoolToWire[int.bools[x]]]};
uniqueID: INT ← int.nbBits+100*int.val+10000*int.mask;
key: ROPE ← Rope.Concat["W", Convert.RopeFromInt[uniqueID]];
[found, ref] ← SymTab.Fetch[cellCache, key];
IF ~found THEN {
obj ← PW.MapFunctionX[design, IntToAdrFn, 0, int.nbBits];
[] ← SymTab.Store[cellCache, key, obj];}
ELSE obj ← NARROW[ref];
END;
forEachItemMakeWire: PWDescr.ForEachItemProc =
BEGIN
obj: PW.ObPtr ← WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => IF bit.val THEN decWireCt ELSE decWireNoCt,
bool: PWDescr.BoolRef => BoolToWire[bool],
int: PWDescr.IntRef => IntToWire[int],
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];
END;
PWDescr.EnumerateItems[descr, forEachItemMakeWire];
wire ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- so far, we find only bits in a pull-up
DescrToWirePU: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [wire: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
forEachItemMakeWire: PWDescr.ForEachItemProc =
BEGIN
obj: PW.ObPtr ← WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => IF bit.val THEN decWirePCt ELSE decWirePNoCt,
ENDCASE => ERROR;
IF flip THEN listOb ← CONS[PW.FlipX[design, obj], listOb]
ELSE listOb ← CONS[obj, listOb];
flip ← ~flip;
END;
flip: BOOLFALSE;
PWDescr.EnumerateItems[descr, forEachItemMakeWire];
wire ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- Descriptor to pull-down chain
DescrToInvPD: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [obj: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
BoolToPD: PROC [bool: PWDescr.BoolRef] RETURNS [obj: PW.ObPtr] =
{obj ← IF bool.val0 THEN decInv ELSE decNoInv2};
IntToPD: PROC [int: PWDescr.IntRef] RETURNS [obj: PW.ObPtr] =
BEGIN
-- check the order of bits
IntToObj: PW.XYFunction = {RETURN[BoolToPD[int.bools[x]]]};
obj ← PW.MapFunctionX[design, IntToObj, 0, int.nbBits];
END;
forEachItem: PWDescr.ForEachItemProc =
{obj: PW.ObPtr ←
WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => obj ← decNoInv,
bool: PWDescr.BoolRef => obj ← BoolToPD[bool],
int: PWDescr.IntRef => obj ← IntToPD[int],
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];};
PWDescr.EnumerateItems[descr, forEachItem];
obj ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- Descriptor to pull-up chain: different from DescrToPD because not only the cells, but also the assembly process is different (flip)
DescrToInvPU: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [obj: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
forEachItem: PWDescr.ForEachItemProc =
{obj: PW.ObPtr ←
WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => obj ←
IF flip THEN decInvPFlip ELSE decInvP,
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];
flip ← ~flip;};
flip: BOOLFALSE;
PWDescr.EnumerateItems[descr, forEachItem];
obj ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- Descriptor to gap. All the wires of an item are passed together
DescrToGapPD: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [gap: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
BoolToGap: PROC [bool: PWDescr.BoolRef] RETURNS [obj: PW.ObPtr] =
{obj ← IF ~bool.val0 THEN decPassX ELSE decPass2};
IntToGap: PROC [int: PWDescr.IntRef] RETURNS [obj: PW.ObPtr] =
BEGIN
IntToAdrFn: PW.XYFunction = {RETURN[BoolToGap[int.bools[x]]]};
obj ← PW.MapFunctionX[design, IntToAdrFn, 0, int.nbBits];
END;
forEachItemMakeWire: PWDescr.ForEachItemProc =
BEGIN
obj: PW.ObPtr ← WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => IF bit.val THEN decGapPass ELSE decGapNoPass,
bool: PWDescr.BoolRef => BoolToGap[bool],
int: PWDescr.IntRef => IntToGap[int],
ENDCASE => ERROR;
listOb ← CONS[obj, listOb];
END;
PWDescr.EnumerateItems[descr, forEachItemMakeWire];
gap ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- so far, we find only bits in a pull-up
DescrToGapPU: PROC [design: CD.Design, descr: PWDescr.Descriptor] RETURNS [gap: PW.ObPtr ← NIL] =
BEGIN
listOb: PW.ListOb ← NIL;
forEachItemMakeWire: PWDescr.ForEachItemProc =
BEGIN
obj: PW.ObPtr ← WITH item.specificRef SELECT FROM
bit: PWDescr.BitRef => IF bit.val THEN decGapPPass ELSE decGapPNoPass,
ENDCASE => ERROR;
IF flip THEN listOb ← CONS[PW.FlipX[design, obj], listOb]
ELSE listOb ← CONS[obj, listOb];
flip ← ~flip;
END;
flip: BOOLFALSE;
PWDescr.EnumerateItems[descr, forEachItemMakeWire];
gap ← PW.AbutListX[design, PW.Reverse[listOb]];
END;
-- A speed-up hack
cellCache: SymTab.Ref;
-- Pull-down of the Nand/Nor of Nand decoder
decGround, decTransistor, decNoTransistor, decZero, decOne, decX: PW.ObPtr;
-- Pull-up of the Nand/Nor of Nand decoder
decNPSep, decPNoTrans, decPNoTransFlip, decPTrans, decPTransFlip, decLeftPrech, decRightPrech, decDriver, norDecAttachUp, norDecAttachDown: PW.ObPtr;
-- Pull-down part of a wire
decWireGround, decWireCt, decWireNoCt, decWireZeroCt, decWireOneCt, decWireX: PW.ObPtr;
-- Pull-up part of a wire, and a special case for the bias voltage generator
decWireNPSep, decWirePCt, decWirePNoCt, decWirePrechNoCt, decWirePrechLeftCt, decWirePrechRightCt, decWireDriver, decBiasVoltage: PW.ObPtr;
-- Pull-down part of an inverter
decInvGround, decNoInv, decNoInv2, decInv, decInvPFlip: PW.ObPtr;
-- Pull-up part of an inverter
devInvNPSep, decInvP, decInvDriver: PW.ObPtr;
-- Pull-down part of a gap
decGapGround, decGapPass, decGapNoPass, decPassX, decPass2: PW.ObPtr;
-- Pull-up part of a gap
decGapNPSep, decGapPPass, decGapPNoPass, decGapDriver: PW.ObPtr;
InitEUControl: PUBLIC PROC [design: CD.Design] =
BEGIN
PW.SetDefaultSource[design, PW.OpenDesign["///eulayout.dale"]];
decTransistor ← PW.Get[design, "decTransistor"];
decNoTransistor ← PW.Get[design, "decNoTransistor"];
decDriver ← PW.Get[design, "decDriver"];
norDecAttachUp ← PW.Get[design, "norDecAttachUp"];
norDecAttachDown ← PW.Get[design, "norDecAttachDown"];
decPNoTrans ← PW.Get[design, "decPNoTrans"];
decPNoTransFlip ← PW.FlipX[design, decPNoTrans];
decPTrans ← PW.Get[design, "decPTrans"];
decPTransFlip ← PW.FlipX[design, decPTrans];
decNPSep ← PW.Get[design, "decNPSep"];
decGround ← PW.Get[design, "decGround"];
decZero ← PW.AbutX[design, decNoTransistor, decTransistor];  -- convention!!!
decOne ← PW.AbutX[design, decTransistor, decNoTransistor];
decX ← PW.AbutX[design, decNoTransistor, decNoTransistor]; 
decLeftPrech ← PW.AbutX[design, decPTrans, decPNoTransFlip];
decRightPrech ← PW.AbutX[design, decPNoTrans, decPTransFlip];
decWireCt ← PW.Get[design, "decWireCt"];
decWireNoCt ← PW.Get[design, "decWireNoCt"];
decWireZeroCt ← PW.AbutX[design, decWireCt, decWireNoCt]; 
decWireOneCt ← PW.AbutX[design, decWireNoCt, decWireCt]; 
decWireX ← PW.AbutX[design, decWireNoCt, decWireNoCt]; 
decWireNPSep ← PW.Get[design, "decWireNPSep"];
decWirePCt ← PW.Get[design, "decWirePCt"];
decWirePNoCt ← PW.Get[design, "decWirePNoCt"];
decWireDriver ← PW.Get[design, "decWireDriver"];
decBiasVoltage ← PW.Get[design, "decBiasVoltage"];
decWireGround ← PW.Get[design, "decWireGround"];
decWirePrechNoCt ← PW.AbutX[design, decWirePNoCt, PW.FlipX[design, decWirePNoCt]];
decWirePrechLeftCt ← PW.AbutX[design, decWirePCt, PW.FlipX[design, decWirePNoCt]];
decWirePrechRightCt ← PW.AbutX[design, decWirePNoCt, PW.FlipX[design, decWirePCt]];
decInvGround ← PW.Get[design, "decInvGround"];
decNoInv ← PW.Get[design, "decNoInv"];
decNoInv2 ← PW.AbutX[design, decNoInv, decNoInv];
decInv ← PW.Get[design, "decInv"];
devInvNPSep ← PW.Get[design, "devInvNPSep"];
decInvP ← PW.Get[design, "decInvP"];
decInvPFlip ← PW.FlipX[design, decInvP];
decInvDriver ← PW.Get[design, "decInvDriver"];
decGapGround ← PW.Get[design, "decGapGround"];
decGapPass ← PW.Get[design, "decGapPass"];
decGapNoPass ← PW.Get[design, "decGapNoPass"];
decPassX ← PW.AbutX[design, decGapNoPass, decGapNoPass];
decPass2 ← PW.AbutX[design, decGapPass, decGapPass];
decGapNPSep ← PW.Get[design, "decGapNPSep"];
decGapPPass ← PW.Get[design, "decGapPPass"];
decGapPNoPass ← PW.Get[design, "decGapPNoPass"];
decGapDriver ← PW.Get[design, "decGapDriver"];
cellCache ← SymTab.Create[mod: 67];
END;
END.