IFUTestUtils.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Curry, October 24, 1986 3:09:23 pm PDT
Don Curry May 1, 1987 12:46:49 pm PDT
Last Edited by: Don Curry November 19, 1987 10:34:49 am PST
DIRECTORY Atom, Cluster, Convert, Core, CoreClasses, CoreOps, CoreFlat, CoreName, Dragon, EU, EUUtils, HandCodingUtil, SymTab, IFUTop, IFUPLAInstrDecode, IFUPLAMainPipeControl, IFUPLAPass, IFUTest, IO, REFBit, Rope, Rosemary, RoseTV, TerminalIO;
IFUTestUtils: CEDAR PROGRAM
IMPORTS Atom, CoreOps, Cluster, Convert, CoreFlat, CoreName, HandCodingUtil, SymTab, IO, REFBit, Rope, Rosemary, RoseTV, TerminalIO
EXPORTS IFUTest =
BEGIN
← &v ← ViewerOps.FindViewer["Interp: World:Local"]
← ViewerOps.DestroyViewer[&v]
Interpreter
← &v ← ViewerOps.FindViewer["Interp: World:Local"]
← &out ← ViewerIO.CreateViewerStreams["Stuffin", &v].out
← IO.PutRope[&out, "&sgf[IFUTestUtils]"]
Debugging Notes
RemoveButton SIFU
RemoveButton SC2
RemoveButton TSet
RemoveButton TSet
RemoveButton RB
RemoveButton TDay
CreateButton cHsty Interpreter; RCompile IFUTestUtils; Run IFUTestUtils; ← &v ← ViewerOps.FindViewer["Interp: World:Local"]; ← &out ← ViewerIO.CreateViewerStreams["Stuffin", &v].out; ← IO.PutRope[&out, "&sgf[IFUTestUtils]"]
CreateButton cHsty Interpreter; RCompile IFUTestUtils; Run IFUTestUtils; ← &v ← ViewerOps.FindViewer["Interp: World:Local"]; ← &out ← ViewerIO.CreateViewerStreams["Stuffin", &v].out; ← IO.PutRope[&out, "&sgf[IFUTestUtils]"]
CreateButton Hsty ← IFUTestUtils.ShowCluster[]
&sgf[IFUTestUtils]
UpdateProc:   TYPE = IFUTest.UpdateProc;
RTVal:    TYPE = RoseTV.RTVal;
ROPE:     TYPE = Rope.ROPE;
NextMacro:   TYPE = IFUPLAInstrDecode.NextMacro;
CondEffect:   TYPE = IFUPLAMainPipeControl.CondEffect;
CondSelects:   TYPE = Dragon.CondSelects;
ALULeftSources:  TYPE = Dragon.ALULeftSources;
ALURightSources: TYPE = Dragon.ALURightSources;
Store2ASources:  TYPE = Dragon.Store2ASources;
ALUOps:    TYPE = Dragon.ALUOps;
PBusFaults:   TYPE = Dragon.PBusFaults;
FaultCode:   TYPE = IFUPLAPass.PBusFaultCode;
AluOpRp: ARRAY ALUOps OF ROPE = ["Or", "And", "VAd2", "BChk", "SAdd", "SSub", "LAdd", "LSub", "Xor", "?9", "FOP", "?11", "VAdd", "VSub", "UAdd", "USub"];
LtSrcRp: ARRAY ALULeftSources OF ROPE = ["a", "r", "c", "?"];
RtSrcRp: ARRAY ALURightSources OF ROPE = ["b", "r", "c", "k", "f", "?", "?", "?"];
StSrcRp: ARRAY Store2ASources  OF ROPE = ["b", "r", "c", "?"];
PhRp:   ARRAY Dragon.Phase OF ROPE = ["A", "B"];
BoolRp:   ARRAY BOOL OF ROPE = [FALSE: "F", TRUE: "T"];
NextMacroRp: ARRAY NextMacro OF ROPE =
["Get", "--?", "-?-", "Jmp", "?--", "Hld", "??-", "???"];
NextMacroRp: ARRAY [0..8) OF ROPE =["Get", "--?", "-?-", "Jmp", "?--", "Hld", "??-", "???"];
CondEffectRp: ARRAY CondEffect OF ROPE = ["macroT", "macroJ", "microJ", "bubble"]; -- %6g
CondSelectRp: ARRAY CondSelects OF ROPE = [ -- %3g
"--", "EZ", "LZ", "LE",  "?4", "NE",  "GE", "GZ",
"Ovf", "BC", "IL", "?11", "?12", "nBC", "nIL", "MFt"];
OpCodeRpRef: HandCodingUtil.NameArray ← HandCodingUtil.GetInstArray[];
OpCodeRp: PROC[op: [0..256)] RETURNS [ROPE] = {RETURN[OpCodeRpRef[LOOPHOLE[op]]]};
DPFaultRp: ARRAY [0..16) OF ROPE = [ -- %3g
"non", "?1","?2","?3","?4","?5","?6","?7", "mem", "io", "pg", "wt", "au", "?13", "?14", "?15"];
CondRope: PROC[rope: ROPE, cond: BOOL] =
{IF cond THEN TerminalIO.PutRope[rope] ELSE WriteSpace[rope.Length[]] };
WriteSpace: PROC[size: INT] = {THROUGH [0..size) DO TerminalIO.PutRope[" "] ENDLOOP};
Signal: SIGNAL = CODE;
ShowCluster: PUBLIC PROC = {
tos: IO.STREAM ← TerminalIO.TOS[];
TerminalIO.PutF["%L\n", IO.char['f]];
TerminalIO.PutRope["TOP\n"];
ShowClusterStates[Cluster.lastKs.stateTop];
TerminalIO.PutRope["FULL\n"];
ShowClusterStates[Cluster.lastKs.stateFull]};
ShowClusterStates: PROC[states: ARRAY [0..Cluster.historySize) OF Cluster.ClusterState] ={};
DisplayType: TYPE =
{eu, cjump,    fetch, xbus, pipe, stack, instr, test};
DisplayTypeRp: ARRAY DisplayType OF ROPE
["EU", "CJump", "Fetch", "Xbus", "Pipe", "Stack", "Instr", "Test"];
ShowAll: PUBLIC PROC = {
FOR type: DisplayType IN [eu..cjump]  DO ShowTop[type] ENDLOOP;
FOR type: DisplayType IN [fetch..test]  DO Show[type]  ENDLOOP};
ShowLast: PUBLIC PROC = {
FOR type: DisplayType IN [eu..cjump]  DO
ShowStates[top, last, type] ENDLOOP;
FOR type: DisplayType IN [fetch..test]  DO
ShowStates[top, last, type];
ShowStates[full, last, type] ENDLOOP};
ShowTop: PUBLIC PROC[type: DisplayType] = {
TerminalIO.PutF["\n%g\n", IO.rope[DisplayTypeRp[type]]];
TerminalIO.PutRope[" TOP\n"];
ShowStates[top, all, type]};
Show: PUBLIC PROC[type: DisplayType] = {
TerminalIO.PutF["%g\n", IO.rope[DisplayTypeRp[type]]];
TerminalIO.PutRope[" TOP\n"];
ShowStates[top, all, type];
TerminalIO.PutRope[" FULL\n"];
ShowStates[full, all, type]};
ShowStates: PROC[which: {top, full}, range: {last, all}, type: DisplayType] = {
states: ARRAY [0..Cluster.historySize) OF Cluster.ClusterState ← IF which=top
THEN Cluster.lastKs.stateTop
ELSE Cluster.lastKs.stateFull;
end: INTIF range=last THEN 1 ELSE Cluster.historySize-1;
tos: IO.STREAM ← TerminalIO.TOS[];
tf:  ROPEIF which=top THEN "T" ELSE "F";
FOR i: INT DECREASING IN [0..end) DO -- state0=state1
ia: IFUTop.IFUState  ← NARROW[states[i+1 ].data[ifu]];
ib: IFUTop.IFUState ← NARROW[states[i  ].data[ifu]];
ea: EU.EUState  ← NARROW[states[i+1 ].data[eu]];
eb: EU.EUState  ← NARROW[states[i  ].data[eu]];
xbus: IFUTop.RegAddrRec ← LOOPHOLE[ib.XBus];
IF states[i].refPh^=a     THEN LOOP;
IF states[i+1].refPh^#a    THEN LOOP;
IF states[i].refPh^#b     THEN LOOP;
IF states[i].refCy^#states[i+1].refCy^ THEN LOOP;
IF states[i].refCy^#ia.cycle   THEN Signal[];
tos.PutF["%3g ", IO.int[ia.cycle] ];
tos.PutF["%g%g %3g ",
IO.char[DisplayTypeRp[type].Fetch[]], IO.rope[tf], IO.int[states[i].refCy^] ];
SELECT type FROM
test => {
tos.PutF["A:%02x ",  IO.int[ ia.aPipe [1][a] ] ];
tos.PutF["%02x ",  IO.int[ ib.aPipe [1][b] ] ];
tos.PutF["B:%02x ",  IO.int[ ia.bPipe [1][a] ] ];
tos.PutF["%02x ",  IO.int[ ib.bPipe [1][b] ] ];
tos.PutF["C:%02x ",  IO.int[ ia.cPipe [1][a] ] ];
tos.PutF["%02x ",  IO.int[ ib.cPipe [1][b] ] ];
tos.PutF["%02x ",  IO.int[ ia.cPipe [2][a] ] ];
tos.PutF["%02x ",  IO.int[ ib.cPipe [2][b] ] ];
tos.PutF["%02x ",  IO.int[ ia.cPipe [3][a] ] ];
tos.PutF["%02x ",  IO.int[ ib.cPipe [3][b] ] ];
tos.PutF["%4g ",   IO.rope[ AluOpRp[  ib.ctlPipe1AB.aluOp ] ] ];
tos.PutF["%4g ",   IO.rope[ AluOpRp[  ib.ctlPipe1BA.aluOp ] ] ];
tos.PutF["%4g ",   IO.rope[ AluOpRp[  ib.ctlPipe2AB.aluOp ] ] ];
};
pipe => {
CondRope[ "Ld1A ",  ia.LoadStage1Ac   ];
CondRope[ "Ld1B ",   ib.LoadStage1Bc   ];
CondRope[ "Ld2A ",  ia.LoadStage2Ac   ];
CondRope[ "(bub) ",  ia.Stage2ABubbleBA];
CondRope[ "Abrt2B ",  ib.Stage2BAbortAB  ];
CondRope[ "Ld3A ",  ia.LoadStage3Ac   ];
CondRope[ "(abrt) ",  ia.Stage3AAbortBA  ];
};
stack => {
tos.PutF["%02x ",    IO.int[ ib.TosBA    ] ];
tos.PutF["%02x ",    IO.int[ ib.BosBA    ] ];
};
instr => {
CondRope[ "* ",        ia.ResetBA    ];
tos.PutF["%2x ",     IO.int[ ia.StateAB    ] ];
CondRope[ "Rdy ",       ia.InstReadyAB   ];
tos.PutF["%5g ", IO.rope[ OpCodeRp[  ia.OpAB     ] ] ];
tos.PutF["%2x ",     IO.int[ ia.AlphaAB    ] ];
tos.PutF["%2x ",     IO.int[ ia.BetaAB     ] ];
tos.PutF["%2x ",     IO.int[ ia.GammaAB    ] ];
tos.PutF["%2x ",     IO.int[ ia.DeltaAB     ] ];
tos.PutF["%g ", IO.rope[ NextMacroRp[ ib.NextMacroBA.ORD ] ] ];
CondRope[ "Rd0 ",       ib.DPCmndIsRd0BA  ];
CondRope[ "Rd2 ",       ib.DPCmndIsRd2BA  ];
CondRope[ "ILck ",       ib.Stage1BHoldBA  ];
tos.PutF["L:%02x ",    IO.int[ ib.LBA     ] ];
tos.PutF["S:%02x ",    IO.int[ ib.SBA     ] ];
};
fetch => {
CondRope[ "Ftch ",    ia.NewFetchBA   ];
tos.PutF["a:%08x ", IO.card[ ia.fetchAddrBA   ] ];
CondRope[ "Rjt ",    ib.IPRejectBA   ];
CondRope[ "Flt ",    ib.IPFaultingBA   ];
CondRope[ "FA ",    ia.FetchingAB   ]; -- Fix these
CondRope[ "FB ",    ib.FetchingBA   ]; -- Fix these
tos.PutF["%02x ", IO.card[ ib.FetchWtAB   ] ];
tos.PutF["%02x ", IO.card[ ib.FetchRdBA   ] ];
tos.PutF["%02x ", IO.card[ ib.FetchBytesM1AB  ] ];
tos.PutF["%x ", IO.card[  ib.wtAB     ] ];
tos.PutF["%x ", IO.card[  ib.rdAB     ] ];
CondRope[ "IRdy ",    ia.InstReadyAB   ];
tos.PutF["d:%08x ", IO.card[ ib.IPData   ] ];
};
xbus => {
tos.PutF["Xa:%08x ", IO.card[ ia.XBus ] ];
tos.PutF["Xb:%08x ", IO.card[ ib.XBus ] ];
tos.PutF["X:%02x ",  IO.int[ xbus.aAddr ] ];
tos.PutF["%02x ",  IO.int[ xbus.bAddr ] ];
tos.PutF["%02x ",  IO.int[ xbus.cAddr ] ];
tos.PutF["l:%g ",   IO.rope[ LtSrcRp[ xbus.aluLeftSrc ] ] ];
tos.PutF["r:%g ",  IO.rope[ RtSrcRp[ xbus.aluRightSrc ] ] ];
tos.PutF["s:%g ",  IO.rope[ StSrcRp[ xbus.storeSrc ] ] ];
CondRope[ "S3C",  xbus.st3AisC  ];
};
cjump => {
tos.PutF["CE2:%6g ", IO.rope[ CondEffectRp[ ia.CondEffect2AB ] ] ];
tos.PutF["CS2:%3g ", IO.rope[ CondSelectRp[ ia.ctlPipe2AB.condSel ] ] ];
CondRope[ "Cond ",         ia.EUCondition2BA  ];
};
eu => {
tos.PutF["%4g ",  IO.rope[ AluOpRp[  ib.ctlPipe2AB.aluOp ] ] ];
tos.PutF["2:%3g ", IO.rope[ CondSelectRp[ ib.ctlPipe2AB.condSel ] ] ];
CondRope[ "Cnd ",        ib.EUCondition2BA  ];
tos.PutF["3:%3g ", IO.rope[ CondSelectRp[ ib.ctlPipe3AB.condSel ] ] ];
CondRope[ "Rd",         ib.ctlPipe3AB.rdFromPBus  ];
CondRope[ "Wt",        ib.ctlPipe3AB.writeToPBus  ];
tos.PutF["%08x ", IO.card[ ea.reg[EUUtils.left]]];
tos.PutF["%08x ", IO.card[ ea.reg[EUUtils.right]]];
tos.PutF["%08x ", IO.card[ eb.reg[EUUtils.r2B]]];
CondRope[ "CAB ",     ea.carryAB  ];
CondRope[ "CBA ",     eb.carryBA  ];
CondRope[ "Rjt ",     ib.DPRejectBA ];
tos.PutF["%3g ",  IO.rope[ DPFaultRp[ ib.DPFaultBA.ORD ] ] ];
};
ENDCASE => ERROR;
TerminalIO.PutRope["\n"] ENDLOOP};
Strip: PROC[path: ROPENIL] RETURNS[ROPE] = {
start: INT;
WHILE (start←path.Find["("]) # -1 DO
path ← Rope.Cat[path.Substr[0,start], path.Substr[path.Index[0, ")"]]] ENDLOOP;
RETURN[path]};
Cell: PROC[a,b: ROPENIL] RETURNS[cell: Core.CellType] = {
RETURN[IF a.Length[]=0
THEN Cluster.lastKs.ifuSimulation.cellType
ELSE CoreFlat.ResolveFlatCellType
[Cluster.lastKs.ifuSimulation.cellType, FlatCellRec[a,b]].cellType]};
State: PROC[a,b: ROPENIL] RETURNS[ref: REF] = {
ref ← Rosemary.GetState
[Cluster.lastKs.ifuSimulation, NEW[CoreFlat.FlatCellTypeRec ← FlatCellRec[a,b]]]};
FlatCellRec: PROC[a,b: ROPENIL] RETURNS[flatCell: CoreFlat.FlatCellTypeRec] = {
flatCell ←
CoreFlat.ParseCellTypePath[Cluster.lastKs.ifuSimulation.cellType, Rope.Cat[a,b]]};
cellNamePathDepth:   INT ← -1;
cellNamePathDepthLimit: INT ← 7;
cellNamePath: SymTab.Ref ← SymTab.Create[];
FindAPath: PROC[cellType: Core.CellType, target: IO.ROPENIL] RETURNS[path: IO.ROPE] = {
AddLevel: PROC[cell: Core.CellType, here: IO.ROPENIL, d: INT] = {
IF d=0
THEN {
name: IO.ROPE ← CoreOps.GetCellTypeName[cell];
IF name.Length[]>0 THEN []←SymTab.Store[cellNamePath, name, here]}
ELSE IF ISTYPE[cell.data, CoreClasses.RecordCellType] THEN {
rec: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR i: INT IN [0..rec.size) DO
AddLevel[rec[i].type, IO.PutFR["%g/%g", IO.rope[here], IO.int[i]], d-1]
ENDLOOP}};
DO
IF SymTab.Fetch[cellNamePath, target].found
THEN RETURN[NARROW[SymTab.Fetch[cellNamePath, target].val]];
IF cellNamePathDepth+1 >= cellNamePathDepthLimit THEN RETURN[NIL];
cellNamePathDepth ← cellNamePathDepth+1;
AddLevel[cellType, "", cellNamePathDepth] ENDLOOP};
FindAPath: PROC[cellType: Core.CellType, target: IO.ROPENIL] RETURNS[path: IO.ROPE] = {
CheckDepth: PROC[cell: Core.CellType, here: IO.ROPENIL, d: INT]
RETURNS[found: BOOL] = {
IF d<1 THEN {
name: IO.ROPE ← CoreOps.GetCellTypeName[cell];
IF name.Length[]>0 THEN SymTab.Store[cellNamePath, name, here];
IF name.Equal[target]
THEN {path ← here; RETURN[TRUE]}
ELSE {path ← NIL;  RETURN[FALSE]};
IF ISTYPE[cell.data, CoreClasses.RecordCellType] THEN {
rec: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR i: INT IN [0..rec.size) DO
IF CheckDepth[rec[i].type, IO.PutFR["%g/%g", IO.rope[here], IO.int[i]], d-1]
THEN RETURN[TRUE] ENDLOOP};
RETURN[FALSE]};
FOR depth: INT ← 0, depth+1 DO
IF CheckDepth[cellType, "", depth].found THEN RETURN[path] ENDLOOP};
PrintWire: PROC[wire: Core.Wire] = {
FinishOld: PROC = {nxtOld.idx ← 0; TerminalIO.PutF["..%g)\n", IO.int[nxtIdx]]};
delayd: BOOLFALSE;
nxtOld: CoreName.SigRec;
nxtIdx: INT ← 0;
FOR i: INT IN [0..wire.size) DO
name: ROPE ← CoreName.WireNm[wire[i]].n;
IF delayd THEN {
test: CoreName.SigRec ← CoreName.NameSig[name];
nxtOld.idx ← test.idx;
IF nxtOld=test THEN {
IF nxtIdx#test.idx
THEN TerminalIO.PutF["..%g) [%g", IO.int[nxtIdx], IO.int[test.idx]];
nxtIdx ← test.idx+1; LOOP};
FinishOld[]};
TerminalIO.PutF[" %g", IO.rope[name]];
nxtOld ← CoreName.NameSig[name];
IF nxtOld.idx#-1
THEN {delayd ← TRUE; nxtIdx←nxtOld.idx+1}
ELSE {delayd ← FALSE; TerminalIO.PutF["\n"]};
ENDLOOP;
IF delayd THEN FinishOld[]};
InitStates: PUBLIC PROC[sim: Rosemary.Simulation, size: CARDINAL]
RETURNS[states: IFUTest.StateSeq] = {
states ← NEW[IFUTest.StateSeqRec[size]];
FOR i: NAT IN [0..states.size) DO
states[i] ← NEW[IFUTop.IFUStateRec];
ENDLOOP};
UpdateStates: PUBLIC PROC[
sim: Rosemary.Simulation,
states: IFUTest.StateSeq,
pass: INT,
qph: IFUTop.QPh ] = {
temp: IFUTop.IFUState ← states[states.size-1];
FOR i: NAT DECREASING IN [1..states.size) DO states[i] ← states[i-1] ENDLOOP;
states[0] ← temp;
UpdateState[sim, states[0], pass, qph]};
inner: ROPE;
leftCol, fetchIndexing, fetchRdDecode, fetchWtDecode, fetchControl, stackDecode, stackControlA, stackControlB, ltDrPadIO, mainPipeControl, interlock, stackIndexing: ROPE;
dataCol, instrReg, fetchAddr, fetchBuf, fetchInst, xaForm, pcForm, pcFormBot, pcFormTop, stack, pcStkIO, stackBuf, statStkIO, lsForm, lsFormTop, lsFormBot, abForm, cpipe: ROPE;
rightCol: ROPE;
instrDecode, rtDrPadIO, idInDr, idOutDr: ROPE;
idBdy0, idBdy1, idBdy2, idBdy3, idBdy4, idBdy5, idBdy6: ROPE;
cachedXFers: LIST OF RTVal ← NIL;
GetXFers: PROC[root: Core.CellType] RETURNS[xfers: LIST OF RTVal] = {
IF cachedXFers#NIL THEN RETURN[cachedXFers] ELSE {
Path: PROC[target: IO.ROPE] RETURNS[path: IO.ROPE] = {
TerminalIO.PutF["Path: %20g = ", IO.rope[target]];
path ← FindAPath[root, target];
TerminalIO.PutF["%g\n", IO.rope[IF path#NIL THEN path ELSE "???"]]};
inner    ← Path["IFUInner"];
leftCol   ← Path["LeftColumn"];
fetchIndexing ← Path["FetchIndexingMain"];
fetchRdDecode ← Path["FetchRdDecode"];
fetchWtDecode ← Path["FetchWtDecode"];
fetchControl  ← Path["FetchControl"];
stackDecode  ← Path["StackDecode"];
stackControlA ← Path["StackControlA"];
stackControlB ← Path["StackControlB"];
ltDrPadIO   ← Path["LtDrPadIO"];
mainPipeControl ← Path["MainPipeControl"];
interlock   ← Path["Interlock"];
stackIndexing ← Path["StackIndexing"];
dataCol   ← Path["DataColumn"];
instrReg   ← Path["InstrReg"];
 fetchAddr ← Path["FetchAddr"];
 fetchBuf  ← Path["FetchBuf"];
 fetchInst  ← Path["FetchInst"];
 xaForm  ← Path["XaForm"];
pcForm   ← Path["PCForm"];
 pcFormTop ← Path["PCFormTop"];
 pcFormBot ← Path["PCFormBot"];
stack    ← Path["Stack"];
 pcStkIO  ← Path["PCStkIO"];
 stackBuf  ← Path["StackBuf"];
 statStkIO  ← Path["StatStkIO"];
lsForm   ← Path["LSForm"];
 lsFormTop ← Path["LSFormTop"];
 lsFormBot ← Path["LSFormBot"];
abForm   ← Path["ABFormMain"];
cpipe    ← Path["ControlPipe"];
rightCol   ← Path["RightColumn"];
cachedXFers ← xfers ← LIST[ 
RoseTV.New[dataCol,   "StateAB",    StateAB,    FALSE, FBN],
RoseTV.New[dataCol,    "InstReadyAB",   InstReadyAB,  FALSE, FBN],
RoseTV.New[dataCol,   "OpAB",     OpAB,    FALSE, FBN],
RoseTV.New[dataCol,   "AlphaAB",    AlphaAB,   FALSE, FBN],
RoseTV.New[dataCol,   "BetaAB",    BetaAB,    FALSE, FBN],
RoseTV.New[xaForm,   "GammaAB",    GammaAB,   FALSE, FBN],
RoseTV.New[xaForm,   "DeltaAB",    DeltaAB,    FALSE, FBN],
RoseTV.New[stackIndexing, "TosBA",     TosBA,    FALSE, FBN],
RoseTV.New[stackIndexing, "BosBA",     BosBA,    FALSE, FBN],
RoseTV.New[lsFormBot,  "LBA",     LBA,     FALSE, FBN],
RoseTV.New[lsFormBot,  "SBA",     SBA,     FALSE, FBN],
RoseTV.New[instrReg,   "NextMacroBA",   NextMacroBA,  FALSE, FBN],
RoseTV.New[cpipe,    "DPCmndIsRd0BA",  DPCmndIsRd0BA, FALSE, FBN],
RoseTV.New[cpipe,    "DPCmndIsRd2BA",  DPCmndIsRd2BA, FALSE, FBN],
RoseTV.New[mainPipeControl, "Stage1BHoldBA",  Stage1BHoldBA,  FALSE, FBN],
RoseTV.New[pcFormBot,  "LoadStage1Ac",   LoadStage1Ac,  FALSE, FBN],
RoseTV.New[pcFormBot,  "LoadStage1Bc",   LoadStage1Bc,  FALSE, FBN],
RoseTV.New[pcFormBot,  "LoadStage2Ac",   LoadStage2Ac,  FALSE, FBN],
RoseTV.New[cpipe,  "Stage2BAB.Stage2BAbortAB", Stage2BAbortAB, FALSE, FBN],
RoseTV.New[pcFormBot,  "LoadStage3Ac",   LoadStage3Ac,  FALSE, FBN],
RoseTV.New[cpipe,  "Stage3ABA.Stage3AAbortBA", Stage3AAbortBA, FALSE, FBN],
RoseTV.New[cpipe,    "CondEffect2BA",  CondEffect2BA,  FALSE, FBN],
RoseTV.New[fetchControl,  "NewFetchBA",   NewFetchBA,  FALSE, FBN],
RoseTV.New[fetchAddr,  "FetchAddrBA",   FetchAddrBA,  FALSE, FBN],
RoseTV.New[dataCol,   "IPData",     IPData,    FALSE, FBN],
RoseTV.New[fetchWtDecode, "FetchWtAB",   FetchWtAB,   FALSE, FBN],
RoseTV.New[fetchRdDecode, "FetchRdBA",   FetchRdBA,   FALSE, FBN],
RoseTV.New[fetchIndexing, "FetchBytesM1AB",  FetchBytesM1AB, FALSE, FBN],
RoseTV.New[dataCol,   "XBus",     XBus,     FALSE, FBN],
RoseTV.New[dataCol,   "DPFaultingBA",  DPFaultingBA,  FALSE, FBN],
RoseTV.New[rightCol,   "DPFaultCodeBA",  DPFaultCodeBA,  FALSE, FBN],
RoseTV.New[dataCol,   "DPRejectBA",   DPRejectBA,   FALSE, FBN],
RoseTV.New[leftCol,   "IPRejectBA",   IPRejectBA,   FALSE, FBN],
RoseTV.New[leftCol,   "IPFaultingBA",   IPFaultingBA,  FALSE, FBN],
RoseTV.New[leftCol,   "FetchingBA",   FetchingBA,   FALSE, FBN],
RoseTV.New[cpipe,    "EUAluOp2AB",   AluOp2AB,   FALSE, FBN],
RoseTV.New[abForm,   "A1AB",     A1AB,     FALSE, FBN],
RoseTV.New[abForm,   "A1BA",     A1BA,     FALSE, FBN],
RoseTV.New[abForm,   "B1AB",     B1AB,     FALSE, FBN],
RoseTV.New[abForm,   "B1BA",     B1BA,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C1AB",     C1AB,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C1BA",     C1BA,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C2AB",     C2AB,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C2BA",     C2BA,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C3AB",     C3AB,     FALSE, FBN],
RoseTV.New[lsFormBot,  "C3BA",     C3BA,     FALSE, FBN],
RoseTV.New[leftCol,   "ResetBA",    ResetBA,    FALSE, FBN]];
}};
IFUTop.IFUState
UpdateState: PUBLIC UpdateProc = {
Init nodes known to have bad values
XBus^    ← state.XBus;
RoseTV.XFerList[sim, GetXFers[sim.cellType]];
state.cycle    ← pass;
state.ph     ← qph;
state.StateAB    ← StateAB^;
state.InstReadyAB  ← InstReadyAB^;
state.OpAB    ← OpAB^;
state.AlphaAB   ← AlphaAB^;
state.BetaAB    ← BetaAB^;
state.GammaAB   ← GammaAB^;
state.DeltaAB    ← DeltaAB^;
state.TosBA    ← TosBA^;
state.BosBA    ← BosBA^;
state.LBA     ← LBA^;
state.SBA     ← SBA^;
state.NextMacroBA  ← NextMacroBA^;
state.DPCmndIsRd0BA ← DPCmndIsRd0BA^;
state.DPCmndIsRd2BA ← DPCmndIsRd2BA^;
state.Stage1BHoldBA  ← Stage1BHoldBA^;
state.LoadStage1Ac  ← LoadStage1Ac^;
state.LoadStage1Bc  ← LoadStage1Bc^;
state.LoadStage2Ac  ← LoadStage2Ac^;
state.Stage2BAbortAB ← Stage2BAbortAB^;
state.LoadStage3Ac  ← LoadStage3Ac^;
state.Stage3AAbortBA ← Stage3AAbortBA^;
state.CondEffect2BA  ← CondEffect2BA^;
state.NewFetchBA  ← NewFetchBA^;
state.fetchAddrBA  ← FetchAddrBA^;
state.IPData    ← IPData^;
state.FetchWtAB   ← FetchWtAB^;
state.FetchRdBA   ← FetchRdBA^;
state.FetchBytesM1AB ← FetchBytesM1AB^;
state.XBus    ← XBus^;
state.DPFaultBA   ← IF DPFaultingBA^
THEN LOOPHOLE[8+DPFaultCodeBA^.ORD, PBusFaults] ELSE none;
state.DPRejectBA  ← DPRejectBA^;
state.IPRejectBA   ← IPRejectBA^;
state.IPFaultingBA  ← IPFaultingBA^;
state.FetchingBA  ← FetchingBA^;
state.ctlPipe2AB.aluOp ← AluOp2AB^;
state.aPipe[1][a]   ← A1AB^;
state.aPipe[1][b]   ← A1BA^;
state.bPipe[1][a]   ← B1AB^;
state.bPipe[1][b]   ← B1BA^;
state.cPipe[1][a]   ← C1AB^;
state.cPipe[1][b]   ← C1BA^;
state.cPipe[2][a]   ← C2AB^;
state.cPipe[2][b]   ← C2BA^;
state.cPipe[3][a]   ← C3AB^;
state.cPipe[3][b]   ← C3BA^;
state.ResetBA    ← ResetBA^;
IF state.ph = B THEN ShowLast[]};
StateAB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
InstReadyAB:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
OpAB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
AlphaAB:    REF Dragon.HexByte ← NEW[Dragon.HexByte];
BetaAB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
GammaAB:    REF Dragon.HexByte ← NEW[Dragon.HexByte];
DeltaAB:    REF Dragon.HexByte ← NEW[Dragon.HexByte];
TosBA:     REF [0..32)    ← NEW[[0..32)];
BosBA:     REF [0..32)    ← NEW[[0..32)];
LBA:      REF Dragon.HexByte ← NEW[Dragon.HexByte];
SBA:      REF Dragon.HexByte ← NEW[Dragon.HexByte];
NextMacroBA:   REF NextMacro   ← NEW[NextMacro];
DPCmndIsRd0BA:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
DPCmndIsRd2BA:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
Stage1BHoldBA:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
LoadStage1Ac:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
LoadStage1Bc:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
LoadStage2Ac:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
Stage2BAbortAB:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
LoadStage3Ac:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
Stage3AAbortBA:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
CondEffect2BA:  REF CondEffect   ← NEW[CondEffect];
NewFetchBA:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
FetchAddrBA:   REF RoseTV.LongCard ← NEW[RoseTV.LongCard];
IPData:     REF RoseTV.LongCard ← NEW[RoseTV.LongCard];
FetchWtAB:   REF [0..4)     ← NEW[[0..4)];
FetchRdBA:   REF [0..16)    ← NEW[[0..16)];
FetchBytesM1AB: REF [0..32)    ← NEW[[0..32)];
XBus:     REF RoseTV.LongCard ← NEW[RoseTV.LongCard];
DPFaultingBA:  REF RoseTV.Bool  ← NEW[RoseTV.Bool];
DPFaultCodeBA:  REF FaultCode   ← NEW[FaultCode];
DPRejectBA:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
IPRejectBA:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
IPFaultingBA:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
FetchingBA:   REF RoseTV.Bool  ← NEW[RoseTV.Bool];
AluOp2AB:    REF ALUOps    ← NEW[ALUOps];
A1AB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
A1BA:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
B1AB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
B1BA:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C1AB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C1BA:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C2AB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C2BA:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C3AB:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
C3BA:     REF Dragon.HexByte ← NEW[Dragon.HexByte];
ResetBA:    REF RoseTV.Bool  ← NEW[RoseTV.Bool];
FBN, FieldBitName: RoseTV.FldBitNmProc = { -- only called for multibit unstructured fields
PROC[rtv: RTVal, index: INT] RETURNS[fieldBitNm: ROPE]
SELECT rtv.wwrSize FROM
1    => RETURN[rtv.field];
32    => RETURN[IO.PutFR["%g.%g", IO.rope[rtv.field], IO.int[index]] ];
ENDCASE  => {
bf:   REFBit.Format ← REFBit.Desc[rtv.ref].bitForm;
sigRec: CoreName.SigRec ← CoreName.NameSig[rtv.field];
name:  ROPE ← bf[index].name;
IF name.Length[]=0
THEN {name ← bf[index].nameInv; rtv[index].inverted ← NOT rtv[index].inverted};
name   ← CoreName.BitRopeToSigRope[name];
sigRec.root ← sigRec.root.Cat[CoreName.RootExt[name].root];
IF CoreName.RootExt[name].ext.Length[]#0
THEN { -- numeric
int: INT ← Convert.IntFromRope[CoreName.RootExt[name].ext.Substr[1]];
IF int#index THEN Signal[];
sigRec.idx ← int;
fieldBitNm ← CoreName.SigName[sigRec]}
ELSE { -- enumerated type
fieldBitNm ← Rope.Cat[rtv.field, ".", CoreName.SigName[sigRec]]} } };
CapChar: PROC[sm: CHAR] RETURNS[big: CHAR] =
{RETURN[IF sm IN ['a..'z] THEN sm + LOOPHOLE['A - 'a] ELSE sm]};
CapNth: PROC[rope: ROPE, n: INT] RETURNS[ROPE] =
{RETURN[IO.PutFR["%g%g%g",
IO.rope[rope.Substr[0, n]],
IO.char[CapChar[rope.Fetch[n]]],
IO.rope[rope.Substr[n+1]]] ]};
ifuUpdateProc: PUBLIC ATOM ← $IFUUpdateProc;
Atom.PutProp[ifuUpdateProc, ifuUpdateProc, NEW[UpdateProc ← UpdateState]];
TerminalIO.PutF["%L\n%g\n", IO.char['f], IO.time[]];
END.