IFUAsmControlPipe: 
CEDAR 
PROGRAM 
IMPORTS Commander, IFUAsm, IFUPW, Rope
EXPORTS IFUAsm =
BEGIN
GND: Rope.ROPE = IFUPW.GND;
VDD: Rope.ROPE = IFUPW.VDD;
XBus: Rope.ROPE = "XBus.";
cpRP: IFUPW.RowParams = IFUPW.IFUDataColNSeq;
Field: TYPE = {name, in, out0, out1, out2}; 
signals: 
ARRAY [0..32) 
OF 
ARRAY Field 
OF Rope.
ROPE = [
["Push",    "0BA", "1BA", "2BA", "3BA"],
["Pop",    "0BA", "1BA", "2BA", "3BA"],
["DrXa2Lev",   "0BA", "1BA", NIL,  NIL],
[NIL,     NIL,  NIL,  NIL,  NIL],
["EUAluOp.0",  "0BA", "2AB", NIL,  NIL],
["EUAluOp.1",  "0BA", "2AB", NIL,  NIL],
["EUAluOp.2",  "0BA", "2AB", NIL,  NIL],
["EUAluOp.3",  "0BA", "2AB", NIL,  NIL],
["EUCondSel.0",  "0BA", "2AB", NIL,  NIL],
["EUCondSel.1",  "0BA", "2AB", NIL,  NIL],
["EUCondSel.2",  "0BA", "2AB", NIL,  NIL],
["EUCondSel.3",  "0BA", "2AB", NIL,  NIL],
["DPCmnd.0",  "0BA", "2BA", NIL,  NIL],
["DPCmnd.1",  "0BA", "2BA", NIL,  NIL],
["DPCmnd.2",  "0BA", "2BA", NIL,  NIL],
["DPCmnd.3",  "0BA", "2BA", NIL,  NIL],
["EUCondEffect.0", "0BA", "2BA", NIL,  NIL],
["EUCondEffect.1", "0BA", "2BA", NIL,  NIL],
["EUSt3AisCBus", "1A",  "2BA", NIL,  NIL],
["EURes3AisCBus", "1A",  "2BA", NIL,  NIL],
["EUWriteToPBus", "0BA", "3AB", NIL,  NIL],
["EURes3BisPBus", "1A",  "3AB", NIL,  NIL],
[NIL,     NIL,  NIL,  NIL,  NIL],
[NIL,     NIL,  NIL,  NIL,  NIL],
["EUAluLeftSrc.0", "1A",  "1BA", NIL,  NIL],
["EUAluLeftSrc.1", "1A",  "1BA", NIL,  NIL],
["EUAluRightSrc.0", "1A",  "1BA", NIL,  NIL],
["EUAluRightSrc.1", "1A",  "1BA", NIL,  NIL],
["EUStore2ASrc.0", "1A",  "1BA", NIL,  NIL],
["EUStore2ASrc.1", "1A",  "1BA", NIL,  NIL],
[NIL,     NIL,  NIL,  NIL,  NIL],
[NIL,     NIL,  NIL,  NIL,  NIL] ];
CPInList:   IFUPW.List = BuildList[in];
CPOutList:  IFUPW.List = BuildList[out];
CPInWd:   LIST OF REF = BuildWd[NIL,  in];
CP1ABWd:  LIST OF REF = BuildWd["1AB"];
CP1BxWd:  LIST OF REF = BuildWd["1Bx"];
CP1BAWd:  LIST OF REF = BuildWd["1BA"];
CP2AxWd:  LIST OF REF = BuildWd["2Ax"];
CP2ABWd:  LIST OF REF = BuildWd["2AB"];
CP2BAWd:  LIST OF REF = BuildWd["2BA"];
CP3AxWd:  LIST OF REF = BuildWd["3Ax"];
CP3ABWd:  LIST OF REF = BuildWd["3AB"];
CP3BAWd:  LIST OF REF = BuildWd["3BA"];
CPOut0Wd:  LIST OF REF = BuildWd[NIL,  out0];
CPOut1Wd:  LIST OF REF = BuildWd[NIL,  out1];
CPOut2Wd:  LIST OF REF = BuildWd[NIL,  out2];
euDControls: 
IFUPW.List = 
IFUPW.List8[
"EUAluLeftSrc1BA.0", "EUAluLeftSrc1BA.1",
"EUAluRightSrc1BA.0", "EUAluRightSrc1BA.1",
"EUStore2ASrc1BA.0", "EUStore2ASrc1BA.1",
NIL, NIL];
CPSwitchInTop: 
LIST 
OF 
REF = 
IFUPW.LISTn[
"XBus.",
NIL,
NIL,
LIST[NIL, NIL, NIL,  euDControls]];
CPSwitchIn: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.SwitchBoxRow[
design: design,
name:  "IFUAsmControlPipe.CPSwitchIn",
rowType: IFUPW.cmosMet2,
topRP: cpRP,
top:  CPSwitchInTop,
left:  CPInList,
right:  CPOutList,
bot:  LIST[XBus, CPInWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
botRP:  cpRP ]};
 
CPLatch1A: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch1A",
type:   IFUPW.LISTn["GPLatch"],
leftCtl: LIST["PhA", "VBB"],
top:  LIST[XBus, CPInWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
in:   LIST[CPInWd],
out:  LIST[CP1ABWd],
bot:  LIST[XBus, CP1ABWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPMux1AB: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUMuxRow[
design: design,
name:  "IFUAsmControlPipe.CPMux1AB",
top:  LIST[XBus, CP1ABWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
leftCtl: LIST["Pipe1KillAB", "Pipe1AdvAB"],
in:   LIST[GND, CP1ABWd],
out:  LIST[CP1BxWd],
bot:  LIST[XBus, NIL, CP1BxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPLatch1B: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch1B",
type:   IFUPW.LISTn["GPLatch"],
leftCtl: LIST["NotPipe1CycBc", "VBB"],
top:  LIST[XBus, CP1BAWd, CP1BxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
in:   LIST[CP1BxWd],
out:  LIST[CP1BAWd],
bot:  LIST[XBus, CP1BAWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPMux1BA: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUMuxRow[
design: design,
name:  "IFUAsmControlPipe.CPMux1BA",
top:  LIST[XBus, CP1BAWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
leftCtl: LIST["Pipe2CycAB", "Pipe2KillAB", "Pipe2AdvAB"],
in:   LIST[CP2BAWd, GND, CP1BAWd],
out:  LIST[CP2AxWd],
bot:  LIST[XBus, CP2BAWd, CP2AxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPLatch2A: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch2A",
type:   IFUPW.LISTn["GPLatch"],
leftCtl: LIST["PhA", "VBB"],
top:  LIST[XBus, CP2BAWd, CP2AxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
in:   LIST[CP2AxWd],
out:  LIST[CP2ABWd],
bot:  LIST[XBus, CP2BAWd, CP2ABWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPLatch2B: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch2B",
type:   IFUPW.LISTn["GPLatch"],
leftCtl: LIST["PhB", "VBB"],
top:  LIST[XBus, CP2BAWd, CP2ABWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
in:   LIST[CP2ABWd],
out:  LIST[CP2BAWd],
bot:  LIST[XBus, CP2BAWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPMux3A: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUMuxRow[
design: design,
name:  "IFUAsmControlPipe.CPMux3A",
top:  LIST[XBus, CP2BAWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
leftCtl: LIST["Pipe3CycAB", "Pipe3TrapAB", "Pipe3FaultAB", "Pipe3AdvAB"],
in:   LIST[CP3BAWd, GND, GND, CP2BAWd],
out:  LIST[CP3AxWd],
bot:  LIST[XBus, CP3BAWd, CP3AxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPLatch3A: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch3A",
type:   IFUPW.LISTn["GPLatch"],
leftCtl: LIST["PhA", "VBB"],
top:  LIST[XBus, CP3BAWd, CP3AxWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
in:   LIST[CP3AxWd],
out:  LIST[CP3ABWd],
bot:  LIST[XBus, CP3BAWd, CP3ABWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
CPLatch3B: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.IFUGPCellRow[
design: design,
name:  "IFUAsmControlPipe.CPLatch3B",
type:   IFUPW.LISTn["GPLatch"],
top:  LIST[XBus, CP3BAWd, CP3ABWd, CPOut0Wd, CPOut1Wd, CPOut2Wd],
leftCtl: LIST["PhB", "VBB"], 
in:   LIST[CP3ABWd],
out:  LIST[CP3BAWd],
bot:  LIST[XBus, CP3BAWd, NIL, CPOut0Wd, CPOut1Wd, CPOut2Wd],
rp:   cpRP ]};
 
Drop all but XBus here **********************************************
 
XBusLeft: IFUPW.List = LIST[
"XBus.00","XBus.01","XBus.02","XBus.03","XBus.04","XBus.05","XBus.06","XBus.07", -- pads
"XBus.10","XBus.11","XBus.12","XBus.13","XBus.14","XBus.15","XBus.16","XBus.17", -- decode
"XBus.20","XBus.21","XBus.22","XBus.23","XBus.24","XBus.25","XBus.26","XBus.27"]; -- decode
 
XBusRight: IFUPW.List = LIST
["XBus.37","XBus.36","XBus.35","XBus.34","XBus.33","XBus.32","XBus.31","XBus.30"]; -- pads
 
XBusMiddle: LIST OF REF = LIST[
LIST["XBus.10", NIL, "XBus.11", NIL, "XBus.12", NIL, "XBus.13", NIL],   -- pads
LIST["XBus.14", NIL, "XBus.15", NIL, "XBus.16", NIL, "XBus.17", NIL],   -- pads
LIST["XBus.20", NIL, "XBus.21", NIL, "XBus.22", NIL, "XBus.23", NIL],   -- pads
LIST["XBus.24", NIL, "XBus.25", NIL, "XBus.26", NIL, "XBus.27", NIL ] ];  -- pads
 
CPXBusXsformTop: 
LIST 
OF 
REF = 
IFUPW.LISTn[
"XBus."];
CPXBusXsform: 
PROC[design: 
CD.Design] 
RETURNS[cell: 
CD.Object] = {
cell ← 
IFUPW.SwitchBoxRow[
design: design,
name:  "IFUAsmControlPipe.CPXBusXsform",
rowType: IFUPW.cmosMet2,
topRP:  cpRP,
top:  CPXBusXsformTop,
left:  NIL,
right:  NIL,
bot:  CPXBusXsformBot,
botRP:  IFUPW.IFUDataColSeq ]};
 
CPXBusXsformBot: 
LIST 
OF 
REF = 
IFUPW.LISTn[
"XBus."];
CPXBusXsformBot: LIST OF REF = IFUPW.LISTn
[NIL, NIL, NIL, NIL, NIL, NIL, GND, VDD, XBusMiddle];
 
Bottom of Data Column **********************************************
AddRopeToRoot: 
PROC[rope, root: Rope.
ROPE] 
RETURNS[new: Rope.
ROPE] = {
index: INT   ← Rope.Index[root, 0, "."];
ext: Rope.ROPE ← Rope.Substr[root, index];
IF root=NIL OR rope=NIL THEN RETURN[NIL];
new ← Rope.Cat[Rope.Substr[root, 0, index], rope, ext]};
 
BuildWd: 
PROC[rope: Rope.
ROPE, ropeField: Field ← in]
RETURNS[list: LIST OF REF] = {
FOR byte: 
INT 
DECREASING 
IN [0..
cpRP.rngByte) 
DO
blist: LIST OF REF ← NIL;
FOR bit: 
INT 
DECREASING 
IN [0..
cpRP.rngBit) 
DO
index: INT ← byte*cpRP.rngBit + bit;
suffix: Rope.ROPE ← IF rope # NIL THEN rope ELSE signals[index][ropeField];
blist ← CONS[AddRopeToRoot[suffix, signals[index][name]], blist] ENDLOOP;
 
list ← CONS[blist, list] ENDLOOP };
 
 
BuildList: 
PROC[inout: {in, out}] 
RETURNS[list: 
IFUPW.List] = {
Add: 
PROC[lst: 
IFUPW.List, field: Field] 
RETURNS[
IFUPW.List] = {
fieldRope: Rope.ROPE ← signals[index][field];
IF root = NIL OR fieldRope=NIL THEN RETURN[lst];
RETURN[CONS[AddRopeToRoot[fieldRope, root], lst]]};
 
index: INT;
root: Rope.ROPE;
FOR index 
IN [0..
cpRP.rngByte* 
cpRP.rngBit) 
DO
root ← signals[index][name];
IF inout = in
THEN {list ← Add[list, in]}
ELSE {list ← Add[list, out0]; list ← Add[list, out1]; list ← Add[list, out2]}; 
 
 ENDLOOP };
 
 
CatList: 
PROC[list1, list2: 
IFUPW.List] 
RETURNS[new: 
IFUPW.List] = {
IF list1=NIL THEN RETURN[list2];
new ← CatList[list1.rest, list2];
new ← CONS[list1.first, new] };
 
module:  Rope.ROPE ← "IFUAsmControlPipe";
ControlPipe: 
PUBLIC 
IFUPW.Frame ← 
IFUPW.
NFSFUP[module, y, 
LIST[
CPSwitchIn,
CPLatch1A,
CPMux1AB,
CPLatch1B,
CPMux1BA,
CPLatch2A,
CPLatch2B,
CPMux3A,
CPLatch3A,
CPLatch3B,
CPXBusXsform ] ];
ControlPipeCT: Commander.CommandProc =
{IFUPW.AssembleFrame[IFUAsm.RefDesign[], ControlPipe, cmd ] };
Commander.Register   [proc:   ControlPipeCT, key: module];
END.