EU2ControlAlpsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Louis Monier June 19, 1986 4:21:32 pm PDT
Bertrand Serlet October 18, 1986 10:54:56 pm PDT
Last Edited by: Louis Monier September 15, 1986 4:03:05 pm PDT
DIRECTORY Boole, BooleCore, CDSimpleRules, CoreCreate, CoreOps, CoreProperties, Dragon, EU2ControlAlps, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PWCore, PWCoreRoute, PWRoute, Rope, RopeList;
EU2ControlAlpsImpl: CEDAR PROGRAM
IMPORTS Boole, BooleCore, CDSimpleRules, CoreCreate, CoreOps, CoreProperties, EU2LeafUtils, EU2Utils, LayoutCheckpoint, PWCore, Rope, RopeList
EXPORTS EU2ControlAlps =
BEGIN OPEN Boole, BooleCore, CoreCreate, EU2ControlAlps--, EU2Utils--;
ExprProc: TYPE ~ PROC [i: NAT ← 0] RETURNS [Expression];
AppendInput: PROC [public: Wire, wr: WR, inputD: Inputs] RETURNS [ins: Inputs]~ {
AppendOneInput: PROC [wire: Wire] ~ {ins CONS[[input: wire, driver: inv], ins]};
inv: CellType ← EU2LeafUtils.AlpsExtract["InputDriver.sch"];
pub: Wire = FindWire[public, wr];
ins ← inputD;
IF pub.size=0 THEN AppendOneInput[pub] ELSE CoreOps.VisitRootAtomics[pub, AppendOneInput];
};
AppendOutput: PROC [wire: WR, expr: Expression, clock: ROPENIL, outputDrivers: Outputs] RETURNS [Outputs] ~ {
out: CellType ← EU2LeafUtils.AlpsExtract[IF clock=NIL THEN "OutputDriver.sch" ELSE "ClockedOutputDriver.sch"];
RETURN [CONS[
[driver: out,
pas: IF clock=NIL THEN LIST[["VRef", "VRef"]]
ELSE LIST[["Clock", clock], ["VRef", "VRef"]],
output: wire, expr: expr],
outputDrivers]];
};
AppendState: PROC [wire: WR, expr: Expression, clock: ROPE, outputDrivers: Outputs] RETURNS [Outputs] ~ {
out: CellType ← EU2LeafUtils.AlpsExtract["StateOutputDriver.sch"];
IF clock=NIL THEN ERROR; -- need a clock to latch the state
RETURN [CONS[
[driver: out,
pas: LIST[["Latch", clock], ["VRef", "VRef"]],
output: wire, expr: expr],
outputDrivers]];
};
-- To be generated by Alps (Ave, Serlet, programatori te salutant!)
CreateRamControl: PUBLIC PROC RETURNS [cellType: CellType] = {
IF EU2Utils.useRamControlCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["RamControl"]];
BEGIN
inputDrivers: Inputs ← NIL;
outputDrivers: Outputs ← NIL;
expr: Expression ← NIL;
-- public
public: Wire ← Union[
EU2Utils.GenPGnEWires[],   -- Vdd and Gnd
EU2Utils.GenWiresCtrlToRam[],   -- all Select lines, nPrech, dRamRead
EU2Utils.GenWiresRamToCtrl[],   -- ramAdr
WireList[LIST["reject", "hold", "read", "write", Seq["dStateAd", 4], "enWrtIFUPhA", "enWrtIFUPhB", "phA", "nPhB", "VRef",
EU2Utils.GenRegSelWire[EU2Utils.field],  -- selFieldSrc[0..2)
]]];
-- All the wires used as inputs (numbers)
dStateAd: Wire ← FindWire[public, "dStateAd"];
ramAdr: Wire ← FindWire[public, "ramAdr"];
aHi: Wire ← ramAdr[0][0];
bHi: Wire ← ramAdr[1][0];
cHi: Wire ← ramAdr[2][0];
aLow: Wire ← ramAdr[0][1];
bLow: Wire ← ramAdr[1][1];
cLow: Wire ← ramAdr[2][1];
cAdr: Wire ← ramAdr[2];
-- Expressions (booleans)
read: Variable ← FindWire[public, "read"];
write: Variable ← FindWire[public, "write"];
reject: Variable ← FindWire[public, "reject"];
nReject: Expression ← Not[reject];
hold: Variable ← FindWire[public, "hold"];
nHold: Expression ← Not[hold];
AppendRamDriver: PROC [output: WR, expr: Expression] ~ {
outputDrivers ← AppendOutput[output , expr, "phA", outputDrivers];
};
IF aLow.size#2 OR bLow.size#2 OR cLow.size#2 THEN ERROR;
IF aHi.size#6 OR bHi.size#6 OR cHi.size#6 THEN ERROR;
-- Input inverters to the Alps blocks
inputDrivers ← AppendInput[public, "reject", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "hold", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "read", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "write", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "dStateAd", inputDrivers]; -- 4
inputDrivers ← AppendInput[public, ramAdr, inputDrivers]; -- 24
-- Enable Write on the KBus (IFU side); by luck, same timing as ram
outputDrivers ← AppendOutput["enWrtIFUPhA", EqualInt[cAdr, EU2Utils.IFUAdr], NIL, outputDrivers];
-- enWrtIFUPhA ← cAdr=IFUAdr
outputDrivers ← AppendOutput["enWrtIFUPhB", false, NIL, outputDrivers];
-- enWrtIFUPhB ← false (if no // debug, never used, so could be removed)
-- Precharge of the ram
outputDrivers ← AppendOutput["nPrech", true, "nPhB", outputDrivers];
-- nPrech ← nPhB
-- Output drivers, all of the same type: they follow PhA
FOR i: INT IN [0..EU2Utils.nRows) DO
AppendRamDriver[Index["selA", i], EqualInt[aHi, i]];
-- selHi[i][a] ← aAdrH=i
AppendRamDriver[Index["selB", i], EqualInt[bHi, i]];
-- selHi[i][b] ← bAdrH=i
expr ← IF i=EU2Utils.marAdr/4 THEN Or[reject, EqualInt[cHi, i]]
ELSE And[nReject, EqualInt[cHi, i]];
AppendRamDriver[Index["selC", i], expr];
-- selHi[i][c] ← (cAdrH=i).~reject for i#marAdr/4
-- selHi[marAdr/4][c] ← (cAdrH=i)+reject
ENDLOOP;
FOR i: INT IN [0..EU2Utils.sizeSelLow) DO
AppendRamDriver[Index["selALow", i], EqualInt[aLow, i]];
-- selLow[i][a] ← aAdrL=i
AppendRamDriver[Index["selBLow", i], EqualInt[bLow, i]];
-- selLow[i][b] ← bAdrL=i
expr ← IF i=EU2Utils.marAdr MOD 4 THEN Or[reject, EqualInt[cLow, i]]
ELSE And[nReject, EqualInt[cLow, i]];
AppendRamDriver[Index["selCLow", i], expr];
-- selLow[i][c] ← (cAdrL=i).~reject for i#marAdr MOD 4
-- selHi[marAdr MOD 4][c] ← (cAdrL=i)+reject
ENDLOOP;
-- Control for Field register; located here because it requires cAdr; also same timing as ram
outputDrivers ← AppendOutput["selFieldSrc[0]",
And[nReject, nHold, EqualInt[cAdr, EU2Utils.fieldAdr]], "phA", outputDrivers];
-- selFieldSrc[0] ← (cAdr=fieldAdr).~reject.~hold.PhA
outputDrivers ← AppendOutput["selFieldSrc[1]",
And[write, EqualInt[dStateAd, EU2Utils.field]], NIL, outputDrivers];
-- selFieldSrc[1] ← (dStateAd=field).write
outputDrivers ← AppendOutput["selFieldSrc[2]",
And[read, EqualInt[dStateAd, EU2Utils.field]], NIL, outputDrivers];
-- selFieldSrc[2] ← (dStateAd=field).read
-- reading the ram while debugging
outputDrivers ← AppendOutput["dRamRead",
And[read, EqualInt[dStateAd, EU2Utils.ramA]], NIL, outputDrivers];
-- selFieldSrc[2] ← (dStateAd=ramA).read
cellType ← AlpsCell[
name: "RamControl",
public: public,
inputs: inputDrivers,
outputs: outputDrivers,
props: CoreProperties.Props[[$ContactPolyMetal2, NEW[INT ← 20]]]
];
END;
};
GndAndVdd10Met2MinWidth: PUBLIC PWRoute.WireWidthProc = {
wireWidth ← CDSimpleRules.MinWidth[CDSimpleRules.GetLayer[$cmosB, "metal2"]]
*(IF Rope.Equal[netName, "Vdd"] OR Rope.Equal[netName, "Gnd"] THEN 10 ELSE 1);
};
CreateBothAlps: PUBLIC PROC RETURNS [cellType: CellType] ~ {
ctrlTop: CellType ← CreateCondControl[];
ctrlBot: CellType ← CreateDPControl[];
public: Wire ← Union[
CopyAndDeleteNames[ctrlTop.public, LIST["Vdd", "Gnd", "VRef", "phB", "res0", "carryOut", "lz", "kernal", "il"]],
CopyAndDeleteNames[ctrlBot.public]
];
Vdd: Wire ← FindWire[public, "Vdd"];
Gnd: Wire ← FindWire[public, "Gnd"];
condSel: Wire ← FindWire[public, "condSel"];
reject: Wire ← FindWire[public, "reject"];
hold: Wire ← FindWire[public, "hold"];
read: Wire ← FindWire[public, "read"];
write: Wire ← FindWire[public, "write"];
res3BisP: Wire ← FindWire[public, "res3BisP"];
writePBus: Wire ← FindWire[public, "writePBus"];
aluOp: Wire ← FindWire[public, "aluOp"];
dStateAd: Wire ← FindWire[public, "dStateAd"];
il: Wire ← FindWire[public, "il"];
lz: Wire ← FindWire[public, "lz"];
kernal: Wire ← FindWire[public, "kernal"];
zero: Wire ← FindWire[public, "zero"];
ctrl8: Wire ← FindWire[public, "ctrl8"];
opL: Wire ← FindWire[public, "opL"];
opR: Wire ← FindWire[public, "opR"];
res: Wire ← FindWire[public, "res"];
carryOut: Wire ← FindWire[public, "carryOut"];
shift: Wire ← FindWire[public, "shift"];
carryABIn: Wire ← FindWire[public, "carryABIn"];
carryBAIn: Wire ← FindWire[public, "carryBAIn"];
conditionIn: Wire ← FindWire[public, "conditionIn"];
channelData: PWCoreRoute.ChannelData ← NEW[PWCoreRoute.ChannelDataRec ← [
inX: FALSE,
bottomOrLeftWires: LIST[Vdd, Gnd, condSel, reject, res3BisP, writePBus, aluOp],
topOrRightWires: LIST[hold, read, write, dStateAd, il, lz, kernal, zero, ctrl8, opL, opR, res, carryOut, shift, carryABIn, carryBAIn, conditionIn],
trunkLayer: "metal",
branchLayer: "metal2",
extendTopOrRight: FALSE,
extend: TRUE,
wireWidthProc: GndAndVdd10Met2MinWidth
]];
cellType ← Cell[
name: "BothAlps",
public: public,
instances: LIST [
Instance[name: "BottomAlps",
type: PWCore.RotateCellType[ctrlBot, $FlipY]],
Instance[name: "TopAlps",
type: ctrlTop,
pa1: ["res0", "res[0]"]]
]
];
PWCore.SetLayout[cellType, $Channel, $ChannelData, channelData];
};
CreateCondControl: PUBLIC PROC RETURNS [cellType: CellType] ~ {
CondIs: PROC [cond: Dragon.CondSelects] RETURNS [expr: Expression] ~ {
expr ← EqualInt[condSel, Dragon.CondSelects[cond].ORD];
};
public: Wire ← Wires["Vdd", "Gnd", "phB", "condition", "VRef",
Seq["condSel", EU2Utils.sizeCondSelects],  -- from pads
"zero", "carryOut", "res0", -- from data path
"kernal", "lz", "il"];  -- output of DPControl alps block
condSel: Wire ← FindWire[public, "condSel"];
zero: Variable ← FindWire[public, "zero"];
lz: Variable ← FindWire[public, "lz"];
le: Expression ← Or[lz, zero];
kernal: Variable ← FindWire[public, "kernal"];
res0: Variable ← FindWire[public, "res0"];
overflow: Expression ← Xor[lz, res0];
carryOut: Variable ← FindWire[public, "carryOut"];
il: Variable ← FindWire[public, "il"];
cond: Expression ← OrList[LIST[
And[CondIs[False], false],
And[CondIs[EZ], zero],
And[CondIs[LZ], lz],
And[CondIs[LE], le],
And[CondIs[AddressCheckFault], kernal],
And[CondIs[NE], Not[zero]],
And[CondIs[GE], Not[lz]],
And[CondIs[GZ], Not[le]],
And[CondIs[OvFl], overflow],
And[CondIs[BC], Not[carryOut]],
And[CondIs[IL], il],
And[CondIs[NotBC], carryOut],
And[CondIs[NotIL], Not[il]],
And[CondIs[ModeFault], true]
]];
inputDrivers: Inputs ← NIL;
outputDrivers: Outputs ← NIL;
inputDrivers ← AppendInput[public, "condSel", inputDrivers]; -- 4
inputDrivers ← AppendInput[public, "zero", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "carryOut", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "res0", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "kernal", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "lz", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "il", inputDrivers]; -- 1
outputDrivers ← AppendState["condition", cond, "phB", outputDrivers];
cellType ← AlpsCell[
name: "CondControl",
public: public,
inputs: inputDrivers,
outputs: outputDrivers
];
};
-- Creates the control for the bottom of the Datapath
CreateDPControl: PUBLIC PROC RETURNS [cellType: CellType] = {
IF EU2Utils.useDPControlCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["DPControl"]];
BEGIN
MakeSelExpr: PROC [reg: EU2Utils.PipeRange, exprProc: ExprProc, clock: ROPENIL] ~ {
size: NAT ← EU2Utils.sources[reg].sizeSel;
FOR i: INT IN [0..size) DO
outputDrivers ← AppendOutput[
wire: Index[EU2Utils.sources[reg].nameSel, i],
expr: exprProc[i],
clock: clock,
outputDrivers: outputDrivers];
ENDLOOP;
outputDrivers ← AppendOutput[
wire: Index[EU2Utils.sources[reg].nameSel, size],
expr: And[write, EqualInt[dStateAd, reg]],
clock: NIL,
outputDrivers: outputDrivers];
outputDrivers ← AppendOutput[
wire: Index[EU2Utils.sources[reg].nameSel, size+1],
expr: And[read, EqualInt[dStateAd, reg]],
clock: NIL,
outputDrivers: outputDrivers];
};
inputDrivers: Inputs ← NIL;
outputDrivers: Outputs ← NIL;
public: Wire ← Union[
WireList[LIST["Vdd", "Gnd", "phA", "phB", "carryBA", "carryBAIn", "carryAB", "carryABIn", "kernal", "il", "lz", "enWrtPBusPhA", "enWrtPBusPhB", "conditionIn", Seq["ctrl8", 8], "writePBus", "res3BisP", "reject", Seq["aluOp", EU2Utils.sizeALUOps], "hold", "read", "write", Seq["dStateAd", 4], "VRef" ]],
Wires[EU2Utils.GenRegSelWire[EU2Utils.left],
EU2Utils.GenRegSelWire[EU2Utils.right],
EU2Utils.GenRegSelWire[EU2Utils.st2A],
EU2Utils.GenRegSelWire[EU2Utils.st2B],
EU2Utils.GenRegSelWire[EU2Utils.st3A],
EU2Utils.GenRegSelWire[EU2Utils.kReg],
EU2Utils.GenRegSelWire[EU2Utils.r2B],
EU2Utils.GenRegSelWire[EU2Utils.r3A],
EU2Utils.GenRegSelWire[EU2Utils.r3B],
EU2Utils.GenRegSelWire[EU2Utils.dataIn],
Seq["selcBusSrc", 3]],
EU2Utils.GenWiresCtrlToALU[],
Wires["carryOut", Seq["res", 8], Seq["opL", 3], Seq["opR", 3], Seq["shift", 6], Seq["sh", EU2Utils.wordSize+1]]];
-- All the wires used as inputs (numbers)
ctrl8: Wire ← FindWire[public, "ctrl8"];
leftSrc: Wire ← Range[ctrl8, 1, 2];
rightSrc: Wire ← Range[ctrl8, 3, 3];
st2ASrc: Wire ← Range[ctrl8, 6, 2];
res: Wire ← FindWire[public, "res"];
opL: Wire ← FindWire[public, "opL"];
opR: Wire ← FindWire[public, "opR"];
shift: Wire ← FindWire[public, "shift"];
aluOp: Wire ← FindWire[public, "aluOp"];
dStateAd: Wire ← FindWire[public, "dStateAd"];
-- Expressions (booleans)
reject: Variable ← FindWire[public, "reject"]; -- latched on PhB in the pad
nReject: Expression ← Not[reject];
read: Variable ← FindWire[public, "read"];
write: Variable ← FindWire[public, "write"];
hold: Variable ← FindWire[public, "hold"];
nHold: Expression ← Not[hold];
fetch: Variable ← FindWire[public, "res3BisP"];
store: Variable ← FindWire[public, "writePBus"];
st3AisC: Variable ← FindWire[public, ctrl8[0]];
opL0: Variable ← FindWire[public, opL[0]];
opR0: Variable ← FindWire[public, opR[0]];
carryOut: Variable ← FindWire[public, "carryOut"];
carryBAIn: Variable ← FindWire[public, "carryBAIn"];
carryABIn: Variable ← FindWire[public, "carryABIn"];
conditionIn: Variable ← FindWire[public, "conditionIn"];
-- PhA latches
LeftExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[leftSrc, i]]]};
selLeftSrc[i] ← PhA . (leftSrc=i) . ~reject . ~hold
RightExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[rightSrc, i]]]};
-- selRightSrc[i] ← PhA . (rightSrc=i) . ~reject . ~hold
St2AExpr: ExprProc = {RETURN[And[nReject, nHold, EqualInt[st2ASrc, i]]]};
-- selSt2ASrc[i] ← PhA . (st2ASrc=i) . ~reject . ~hold
R3AExpr: ExprProc = {RETURN[And[nReject, nHold]]};
-- selRes3ABSrc ← PhA . ~reject . ~hold
St3AExpr: ExprProc = {RETURN[
SELECT i FROM
0 => And[nReject, nHold, Not[st3AisC]],
1 => And[nReject, nHold, st3AisC],
ENDCASE => ERROR]};
-- selSt3ABSrc[st2B] ← PhA . ~st3AisC . ~reject . ~hold
-- selSt3ABSrc[cBus] ← PhA . st3AisC . ~reject . ~hold
-- PhB latches
KRegExpr: ExprProc = {RETURN[nHold]};
-- selKRegAdr ← PhB . ~hold
R2BExpr: ExprProc = {RETURN[
SELECT i FROM
0 => And[nHold, Nor[    -- aluOut 
OpIs[FOP],   -- neither FOP
OpIs[BndChk]]],  -- nor BndChk
1 => And[nHold, OpIs[FOP]], -- fuOut
2 => And[nHold, OpIs[BndChk]], -- left
ENDCASE => ERROR]};
-- selRes2BASrc[aluOut] ← PhB . ~hold . (aluOp=FOP)
-- selRes2BASrc[fuOut] ← PhB . ~hold . (aluOp#FOP)
-- selRes2BASrc[left] ← PhB . ~hold . (aluOp=BndChk)
St2BExpr: ExprProc = {RETURN[nHold]};
-- selSt2BASrc ← PhB . ~hold
R3BExpr: ExprProc = {RETURN[nHold]};
-- selRes3BASrc[tBus] ← PhB . ~hold
DataInExpr: ExprProc = {RETURN[nHold]};
-- selDataInSrc ← PhB . ~hold
-- Special guys
CBusExpr: ExprProc = {RETURN[ -- use the non-latched reject and a simple driver, no clock!!!
SELECT i FROM
0 => Nand[nReject, store, fetch],  -- r3B
1 => And[nReject, nHold, fetch],  -- dataIn
2 => Or[EqualInt[dStateAd, EU2Utils.cBus], Not[read]],
ENDCASE => ERROR]};
-- selCBusSrc[r3B] ← (reject + ~fetch + ~store)
-- selCBusSrc[dataIn] ← ~reject . ~hold . fetch
-- selCBusSrc[enW] ← (dStAd=cBus) + ~read
-- Field Unit
ShExpr: ExprProc = {RETURN[EqualInt[shift, i]]};
-- sh[i] ← (shift=i)
-- ALU
CarryInExpr: ExprProc = {RETURN[
OrList[LIST[ -- Or, And, LAdd, Xor, FOP, VAdd and VAdd2 -> false
And[OpIs[VSub], true],  -- I hope Alps does some simplification!!!
And[OpIs[LSub], true],
And[OpIs[BndChk], true],
And[OpIs[SAdd], carryABIn],  -- prev
And[OpIs[SSub], Not[carryABIn]],  -- nprev
And[OpIs[UAdd], carryABIn],
And[OpIs[USub], Not[carryABIn]]
]]
]};
CarryBAExpr: ExprProc = {RETURN[
If[OrList[LIST[OpIs[SAdd], OpIs[SSub], OpIs[LAdd], OpIs[LSub]]],
false,  -- reset carry
If[OpIs[UAdd],
carryOut,  -- get carryOut
If[OpIs[USub],    
Not[carryOut],  -- get ~carryOut
carryABIn]]] -- recycle the carry
]};
CarryABExpr: ExprProc = {RETURN[
If[And[nReject, Not[conditionIn]], carryBAIn, carryABIn] ]};
-- carryAB ← IF ~reject AND ~condition THEN carryBA ELSE carryAB
OpExpr: ExprProc = {
RETURN[SELECT i FROM-- add sub xor or and
0 => Not[InSet[sub]], -- 1 0 1 1 1
1 => InSet[sub, and], -- 0 1 0 0 1
2 => InSet[add, xor], -- 1 0 1 0 0
3 => Not[InSet[add]], -- 0 1 1 1 1
4 => Not[InSet[sub]], -- 1 0 1 1 1
ENDCASE => ERROR];
};
OpType: TYPE = {add, sub, xor, or, and, none};
OpIs: PROC [op: Dragon.ALUOps] RETURNS [expr: Expression] ~ {
expr ← EqualInt[aluOp, Dragon.ALUOps[op].ORD];
};
InSet: PROC [t1, t2: OpType ← none] RETURNS [expr: Expression] ~ {
AddMatchType: PROC [op: OpType] RETURNS [expr: Expression]~ {
expr ← SELECT op FROM
add => Or[OpIs[VAdd2], OpIs[SAdd], OpIs[LAdd], OpIs[VAdd], OpIs[UAdd]],
sub => Or[OpIs[BndChk], OpIs[SSub], OpIs[LSub], OpIs[VSub], OpIs[USub]],
xor => OpIs[Xor],
or => Or[OpIs[Or], OpIs[FOP]],
and => OpIs[And],
ENDCASE => ERROR;
};
expr ← AddMatchType[t1];
IF t2#none THEN expr ← Or[expr, AddMatchType[t2]];
};
IsLispInt: PROC [threeBit: Wire] RETURNS [Expression] ~ {
RETURN[Or[EqualInt[threeBit, 0], EqualInt[threeBit, 7]]];
};
KernalExpr: ExprProc = {RETURN[EqualInt[res, 0]]};
ILExpr: ExprProc = {RETURN[Nand[IsLispInt[Range[res, 0, 3]], IsLispInt[opL], IsLispInt[opR]]]};
LZExpr: ExprProc = {RETURN[Xor[Xor[carryOut, opL0], opR0]]};
WrPBusPhAExpr: ExprProc = {RETURN[And[nReject, nHold]]};
-- enWrtPBusPhA ← ~reject AND ~hold
WrPBusPhBExpr: ExprProc = {RETURN[And[store, nHold]]};
-- enWrtPBusPhB ← store AND ~hold
-- Input to control in order
-- Input Drivers for the (few) signals coming straight from the pads
inputDrivers ← AppendInput[public, "reject", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "hold", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "write", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "read", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "res3BisP", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "writePBus", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "aluOp", inputDrivers];  -- 4
inputDrivers ← AppendInput[public, "dStateAd", inputDrivers];  -- 4
-- Input Drivers for the signals coming from the Data Path
inputDrivers ← AppendInput[public, "conditionIn", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "carryBAIn", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "carryABIn", inputDrivers]; -- 1
inputDrivers ← AppendInput[public, "ctrl8", inputDrivers];  -- 8
inputDrivers ← AppendInput[public, "shift", inputDrivers];  -- 6
inputDrivers ← AppendInput[public, "carryOut", inputDrivers];  -- 1
inputDrivers ← AppendInput[public, "res", inputDrivers];  -- 8
inputDrivers ← AppendInput[public, "opL", inputDrivers];  -- 3
inputDrivers ← AppendInput[public, "opR", inputDrivers];  -- 3
-- Outputs to Data path in order: bottom ones first
-- To pad frame
outputDrivers ← AppendOutput["enWrtPBusPhA", WrPBusPhAExpr[], , outputDrivers];
outputDrivers ← AppendOutput["enWrtPBusPhB", WrPBusPhBExpr[], , outputDrivers];
-- Bottom Registers
MakeSelExpr[EU2Utils.dataIn, DataInExpr, "phB"];
outputDrivers ← AppendOutput[Index["selcBusSrc", 0], CBusExpr[0], , outputDrivers];
outputDrivers ← AppendOutput[Index["selcBusSrc", 1], CBusExpr[1], , outputDrivers];
outputDrivers ← AppendOutput[Index["selcBusSrc", 2], CBusExpr[2], , outputDrivers];
MakeSelExpr[EU2Utils.r3B, R3BExpr, "phB"];
MakeSelExpr[EU2Utils.r3A, R3AExpr, "phA"];
MakeSelExpr[EU2Utils.st3A, St3AExpr, "phA"];
MakeSelExpr[EU2Utils.st2B, St2BExpr, "phB"];
-- Field unit control
FOR i: NAT DECREASING IN [0..EU2Utils.wordSize+1) DO
outputDrivers ← AppendOutput[Index["sh", i], ShExpr[i], NIL, outputDrivers];
ENDLOOP;
-- res2BA Register
MakeSelExpr[EU2Utils.r2B, R2BExpr, "phB"];
-- ALU control
FOR i: NAT IN [0..5) DO
outputDrivers ← AppendOutput[Index["op", i], OpExpr[i], NIL, outputDrivers];
ENDLOOP;
outputDrivers ← AppendOutput["carryIn", CarryInExpr[], NIL, outputDrivers];
-- Top Registers
MakeSelExpr[EU2Utils.st2A, St2AExpr, "phA"];
MakeSelExpr[EU2Utils.left, LeftExpr, "phA"];
MakeSelExpr[EU2Utils.right, RightExpr, "phA"];
MakeSelExpr[EU2Utils.kReg, KRegExpr, "phB"];
-- Carry feedback
outputDrivers ← AppendState["carryBA", CarryBAExpr[], "phB", outputDrivers];
outputDrivers ← AppendState["carryAB", CarryABExpr[], "phA", outputDrivers];
-- Sub-expressions to compute Condition
outputDrivers ← AppendOutput["il", ILExpr[], NIL, outputDrivers];
outputDrivers ← AppendOutput["lz", LZExpr[], NIL, outputDrivers];
outputDrivers ← AppendOutput["kernal", KernalExpr[], NIL, outputDrivers];
-- Generate the block Alps
cellType ← AlpsCell[
name: "DPControl",
public: public,
inputs: inputDrivers,
outputs: outputDrivers,
props: CoreProperties.Props[[$ContactPolyMetal2, NEW[INT ← 20]]]
];
END;
};
CopyAndDeleteNames: PROC [public: Wire, names: LIST OF ROPE ← NIL] RETURNS [copiedAndDeleted: Wire] ~ {
listWires: LIST OF Wire ← NIL;
FOR i: NAT IN [0 .. public.size) DO
name: ROPE ← CoreOps.GetShortWireName[public[i]];
IF ~RopeList.Memb[names, name] THEN listWires ← CONS[CoreOps.CopyWire[public[i]], listWires];
ENDLOOP;
copiedAndDeleted ← CoreOps.CreateWire[listWires];
};
CreateControl: PUBLIC PROC RETURNS [cellType: CellType] ~ {
-- To build the public
IF EU2Utils.useControlCheckpoint THEN RETURN [LayoutCheckpoint.Retrieve["Control"]];
BEGIN
ctrlTop: CellType ← CreateRamControl[];
ctrlBot: CellType ← CreateBothAlps[];
public: Wire ← Union[
CopyAndDeleteNames[ctrlTop.public, LIST["Vdd", "Gnd", "VRef", "reject", "hold", "read", "write", "dStateAd", "phA"]],
CopyAndDeleteNames[ctrlBot.public]
];
-- goes throuh
condition: Wire ← FindWire[public, "condition"];
Vdd: Wire ← FindWire[public, "Vdd"];
Gnd: Wire ← FindWire[public, "Gnd"];
-- out to the left
reject: Wire ← FindWire[public, "reject"];
-- out to the right
hold: Wire ← FindWire[public, "hold"];
read: Wire ← FindWire[public, "read"];
write: Wire ← FindWire[public, "write"];
dStateAd: Wire ← FindWire[public, "dStateAd"];
ramAdr: Wire ← FindWire[public, "ramAdr"];
channelData: PWCoreRoute.ChannelData ← NEW[PWCoreRoute.ChannelDataRec ← [
inX: FALSE,
bottomOrLeftWires: LIST[Vdd, Gnd, reject, condition],
topOrRightWires: LIST[ramAdr, hold, read, write, dStateAd, condition],
trunkLayer: "metal",
branchLayer: "metal2",
extendTopOrRight: FALSE,
extend: TRUE,
wireWidthProc: GndAndVdd10Met2MinWidth
]];
cellType ← Cell[
name: "Control",
public: public,
instances: LIST [
Instance[name: "BottomAlps", type: ctrlBot],
Instance[name: "TopAlps", type: ctrlTop]
]
];
PWCore.SetLayout[cellType, $Channel, $ChannelData, channelData];
END;
};
END.
CarryInExpr: ExprProc = {RETURN[
OrList[LIST[ -- Or, And, LAdd, Xor, FOP, VAdd and VAdd2 -> false
And[OpIs[VSub], true],  -- I hope Alps does some simplification!!!
And[OpIs[LSub], true],
And[OpIs[BndChk], true],
And[OpIs[SAdd], carryABIn],  -- prev
And[OpIs[SSub], Not[carryABIn]],  -- nprev
And[OpIs[UAdd], carryABIn],
And[OpIs[USub], Not[carryABIn]]
]]
]};
CarryBAExpr: ExprProc = {RETURN[
OrList[LIST[ -- SAdd, SSub, LAdd and LSub -> false
And[OpIs[VAdd], carryABIn],
And[OpIs[VAdd2], carryABIn],
And[OpIs[VSub], carryABIn],
And[OpIs[BndChk], carryABIn],
And[OpIs[Or], carryABIn],
And[OpIs[And], carryABIn],
And[OpIs[Xor], carryABIn],
And[OpIs[FOP], carryABIn],  -- prev
And[OpIs[UAdd], carryOut],  -- comp
And[OpIs[USub], Not[carryOut]] -- ncomp
]]
]};