SmallCachePmCodeFSM.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created: Douady, Sindhu April 10, 1987 12:50:16 pm PDT
Pradeep Sindhu October 27, 1987 12:15:49 pm PST
Cesar Douady May 13, 1987 3:09:46 pm PDT
Don Curry January 25, 1988 4:27:39 pm PST
Derived from SCPmCodeImpl.mesa 02-Dec-87 16:13:19 PST
Updated from SCPmCodeImpl.mesa 21-Jan-88 15:37:34 PST
This module defines the Processor-side microcode. Note that only the combinatorial part is modeled, and that the input, output, and feedback registers are within a higher level block defined by the schematic PCtl.sch.
In writing the microcode, we have made the following assumption about the speed of this combinatorial block: signals can go through the block in under one clock cycle, so that inputs need to come directly from a clocked register, and outputs need to go directly to a clocked register, with no intervening logic. This structure implies that the minimum delay between the microcode asserting a signal, and that signal having an effect on the input, is two cycles. This minimum delay is, in fact, used for the signal PCtlSetNonFBTIP -> NonFBTIP.
DIRECTORY
BitOps, Core, DynaBusInterface, FSM, IO, SmallCacheLogic, SymTab;
SmallCachePmCodeFSM: CEDAR PROGRAM
IMPORTS BitOps, FSM, SymTab
EXPORTS SmallCacheLogic
~ BEGIN
Microcode States
microStateIndex: INT ← 1;
microStates:  SymTab.Ref ← SymTab.Create[];
RegisterState: PROC[state: IO.ROPE] RETURNS[IO.ROPE] = {
[]←SymTab.Store[microStates, state, NEW[INT ← microStateIndex]];
microStateIndex ← microStateIndex+1;
RETURN[state]};
StateIndex: PUBLIC PROC[state: IO.ROPE] RETURNS[index: INT ← -1] = {
IF ~SymTab.Fetch[microStates, state].found THEN ERROR;
RETURN[ NARROW[SymTab.Fetch[microStates, state].val, REF INT]^]};
StateName: PUBLIC PROC[index: INT] RETURNS[state: IO.ROPENIL] = {
action: SymTab.EachPairAction = {
IF index = NARROW[val, REF INT]^ THEN {state ← key; RETURN[TRUE]}};
IF NOT SymTab.Pairs[microStates, action] THEN ERROR};
Init:        IO.ROPE ← RegisterState["Init"];
ChkPermPC:     IO.ROPE ← RegisterState["ChkPermPC"];
CP1PC:        IO.ROPE ← RegisterState["CP1PC"];
CP2PC:        IO.ROPE ← RegisterState["CP2PC"];
CP3PC:        IO.ROPE ← RegisterState["CP3PC"];
HandleMissPC:    IO.ROPE ← RegisterState["HandleMissPC"];
HM1PC:       IO.ROPE ← RegisterState["HM1PC"];
HM2PC:       IO.ROPE ← RegisterState["HM2PC"];
HM3PPC:       IO.ROPE ← RegisterState["HM3PPC"];
HM3nPPC:      IO.ROPE ← RegisterState["HM3nPPC"];
HM3nRPC:      IO.ROPE ← RegisterState["HM3nRPC"];
HMnMPC:      IO.ROPE ← RegisterState["HMnMPC"];
HMnM11PC:     IO.ROPE ← RegisterState["HMnM11PC"];
HMnM12PC:     IO.ROPE ← RegisterState["HMnM12PC"];
HMnM2PC:      IO.ROPE ← RegisterState["HMnM2PC"];
HMnM3PC:      IO.ROPE ← RegisterState["HMnM3PC"];
HMnM4PC:      IO.ROPE ← RegisterState["HMnM4PC"];
HMRCamReadyPC:   IO.ROPE ← RegisterState["HMRCamReadyPC"];
HMReadRamPC:    IO.ROPE ← RegisterState["HMReadRamPC"];
HMReturn1PC:     IO.ROPE ← RegisterState["HMReturn1PC"];
HMReturn2PC:     IO.ROPE ← RegisterState["HMReturn2PC"];
HMReturn3PC:     IO.ROPE ← RegisterState["HMReturn3PC"];
HMReturn4PC:     IO.ROPE ← RegisterState["HMReturn4PC"];
HMReturn5PC:     IO.ROPE ← RegisterState["HMReturn5PC"];
HMRR2PC:      IO.ROPE ← RegisterState["HMRR2PC"];
HMRR3PC:      IO.ROPE ← RegisterState["HMRR3PC"];
HMRR4PC:      IO.ROPE ← RegisterState["HMRR4PC"];
HMRRCVct2PC:    IO.ROPE ← RegisterState["HMRRCVct2PC"];
HMRRCVct3PC:    IO.ROPE ← RegisterState["HMRRCVct3PC"];
HMRRCVct4PC:    IO.ROPE ← RegisterState["HMRRCVct4PC"];
HMRRCVM3PC:     IO.ROPE ← RegisterState["HMRRCVM3PC"];
HMRRCVM4PC:     IO.ROPE ← RegisterState["HMRRCVM4PC"];
IdlePC:       IO.ROPE ← RegisterState["IdlePC"];
IOR2PC:       IO.ROPE ← RegisterState["IOR2PC"];
IOWritePC:      IO.ROPE ← RegisterState["IOWritePC"];
PCWS3PC:       IO.ROPE ← RegisterState["PCWS3PC"];
PCWS4PC:       IO.ROPE ← RegisterState["PCWS4PC"];
PCWS5PC:       IO.ROPE ← RegisterState["PCWS5PC"];
PCWS6PC:       IO.ROPE ← RegisterState["PCWS6PC"];
PCWS7PC:       IO.ROPE ← RegisterState["PCWS7PC"];
PCWS8PC:       IO.ROPE ← RegisterState["PCWS8PC"];
PCWS9PC:       IO.ROPE ← RegisterState["PCWS9PC"];
PCWS10PC:       IO.ROPE ← RegisterState["PCWS10PC"];
PCWS11PC:       IO.ROPE ← RegisterState["PCWS11PC"];
PCWS12PC:       IO.ROPE ← RegisterState["PCWS12PC"];
PCWS13PC:       IO.ROPE ← RegisterState["PCWS13PC"];
PCWS14PC:       IO.ROPE ← RegisterState["PCWS14PC"];
PCWS14PrimePC:    IO.ROPE ← RegisterState["PCWS14PrimePC"];
PCWS15PC:       IO.ROPE ← RegisterState["PCWS15PC"];
PCWS16PC:       IO.ROPE ← RegisterState["PCWS16PC"];
PCWS17PC:       IO.ROPE ← RegisterState["PCWS17PC"];
PCWSR2PC:      IO.ROPE ← RegisterState["PCWSR2PC"];
PCWSRetryPC:     IO.ROPE ← RegisterState["PCWSRetryPC"];
PSR2PC:       IO.ROPE ← RegisterState["PSR2PC"];
PSR2PrimePC:     IO.ROPE ← RegisterState["PSR2PrimePC"];
PSR3PC:       IO.ROPE ← RegisterState["PSR3PC"];
PSR4PC:       IO.ROPE ← RegisterState["PSR4PC"];
PSRetryPC:      IO.ROPE ← RegisterState["PSRetryPC"];
PSRetryPrimePC:    IO.ROPE ← RegisterState["PSRetryPrimePC"];
PSReturn1PC:     IO.ROPE ← RegisterState["PSReturn1PC"];
PSReturn2PC:     IO.ROPE ← RegisterState["PSReturn2PC"];
PSRCamReadyPC:    IO.ROPE ← RegisterState["PSRCamReadyPC"];
PSRRCVM2PC:      IO.ROPE ← RegisterState["PSRRCVM2PC"];
PSRRCVM3PC:      IO.ROPE ← RegisterState["PSRRCVM3PC"];
PSRRCVM4PC:      IO.ROPE ← RegisterState["PSRRCVM4PC"];
PStorePC:      IO.ROPE ← RegisterState["PStorePC"];
SBTOF2PC:      IO.ROPE ← RegisterState["SBTOF2PC"];
SBTOF3PC:      IO.ROPE ← RegisterState["SBTOF3PC"];
SIOAF2PC:       IO.ROPE ← RegisterState["SIOAF2PC"];
SIOAF3PC:       IO.ROPE ← RegisterState["SIOAF3PC"];
SMAF2PC:       IO.ROPE ← RegisterState["SMAF2PC"];
SMAF3PC:       IO.ROPE ← RegisterState["SMAF3PC"];
StoreBTimeOutFaultPC:  IO.ROPE ← RegisterState["StoreBTimeOutFaultPC"];
StoreMemAccessFaultPC: IO.ROPE ← RegisterState["StoreMemAccessFaultPC"];
StoreIOAccessFaultPC:  IO.ROPE ← RegisterState["StoreIOAccessFaultPC"];
TestReadRamPC:    IO.ROPE ← RegisterState["TestReadRamPC"];
TestReadRCamPC:    IO.ROPE ← RegisterState["TestReadRCamPC"];
TestReadVCamPC:   IO.ROPE ← RegisterState["TestReadVCamPC"];
TestResetVictimPC:   IO.ROPE ← RegisterState["TestResetVictimPC"];
TestShiftVictimPC:   IO.ROPE ← RegisterState["TestShiftVictimPC"];
TRR2PC:       IO.ROPE ← RegisterState["TRR2PC"];
TRR3PC:       IO.ROPE ← RegisterState["TRR3PC"];
TRV2PC:       IO.ROPE ← RegisterState["TRV2PC"];
TRRC2PC:       IO.ROPE ← RegisterState["TRRC2PC"];
TRRC3PC:       IO.ROPE ← RegisterState["TRRC3PC"];
TRRC4PC:       IO.ROPE ← RegisterState["TRRC4PC"];
TRRC5PC:       IO.ROPE ← RegisterState["TRRC5PC"];
TRRC6PC:       IO.ROPE ← RegisterState["TRRC6PC"];
TRVC2PC:       IO.ROPE ← RegisterState["TRVC2PC"];
TRVC3PC:       IO.ROPE ← RegisterState["TRVC3PC"];
TRVC4PC:       IO.ROPE ← RegisterState["TRVC4PC"];
TRVC5PC:       IO.ROPE ← RegisterState["TRVC5PC"];
TRVC6PC:       IO.ROPE ← RegisterState["TRVC6PC"];
TSV2PC:       IO.ROPE ← RegisterState["TSV2PC"];
TSV3PC:       IO.ROPE ← RegisterState["TSV3PC"];
NumPCBits:  PUBLIC NAT ← BitOps.NBits[microStateIndex];
NumStackBits: PUBLIC NAT ← 2;
SmallCachePmCode: PUBLIC PROC
[usePC: BOOLTRUE, reg: FSM.RegisterType ← none, impl: ATOM ← $PLA]
RETURNS [ct: Core.CellType] = {
Constants
machName:  IO.ROPE   ← "SmallCachePmCode";
fsm:    FSM.FSMData ← NIL;
Declare the finite state machine generation procs
ctx:   FSM.Context ← FSM.Create[machName];
IfState:  PROC[s: IO.ROPE]       = {FSM.IfState  [ctx,s]};
If:    PROC[f, v: NAT, m: NATFSM.default] = {FSM.If    [ctx,f,v,m]};
And:   PROC[f, v: NAT, m: NATFSM.default] = {FSM.And   [ctx,f,v,m]};
AddOut:  PROC[f, v: NAT, m: NATFSM.default] = {FSM.AddOut  [ctx,f,v,m]};
EndIf:  PROC           = {FSM.JmpState  [ctx, NIL]};
Constants
T:         NAT = 1;
F:         NAT = 0;
NumPCmdBits:     NAT = 4;
Stack Addresses
FromRead,
FromIORead:     NAT = 0;
FromWrite,
FromIOWrite:     NAT = 1;
FromCWS:      NAT = 2; -- FromCWS encoded as 2 or 3 in HMReturn2PC
ABus Source Codes
ABusPAdd:      NAT = 0;
ABusRqstBuf:     NAT = 1;
ABusVCam:     NAT = 4;
forbidden:      NAT = 5;
ABusCam:      NAT = 6;
ABusRCam:      NAT = 7;
ABusIOOld:     NAT = 8;
ABusIONew:     NAT = 9;
ABusIOAId:     NAT = 12;
ABusIOFault:     NAT = 13;
ABusFault:      NAT = 8;
DBus Source Codes
DBusNoOp:      NAT = 0;
DBusPWtLatch:    NAT = 1;
DBusRRLatch:     NAT = 2;
DBusABus:      NAT = 3;
Array Multiplexer Select Codes
SCmdNoOp:      NAT = 0;
SCmdLRM:      NAT = 1;
SCmdLVM:      NAT = 2;
SCmdVictim:     NAT = 3;
PCmd Defs
PCmdNoOp:      NAT = 7;
PCmdRead:      NAT = 8;
PCmdWrite:      NAT = 9;
PCmdCWS:      NAT = 10;
PCmdDeMap:     NAT = 11;
PCmdIORead:     NAT = 12;
PCmdIOWrite:     NAT = 13;
PCmd14:       NAT = 14; -- used only as mask for PCmdBIOWrite
PCmdBIOWrite:    NAT = 15; -- encoded as 14 or 15 using PCmd14 - djc
BCmd Defs
BCmdBIOW:     NAT = ORD[DynaBusInterface.Cmd.BIOWRqst]/2;
BCmdCWS:      NAT = ORD[DynaBusInterface.Cmd.CWSRqst]/2;
BCmdDeMap:     NAT = ORD[DynaBusInterface.Cmd.DeMapRqst]/2;
BCmdFB:      NAT = ORD[DynaBusInterface.Cmd.FBRqst]/2;
BCmdIOR:      NAT = ORD[DynaBusInterface.Cmd.IORRqst]/2;
BCmdIOW:      NAT = ORD[DynaBusInterface.Cmd.IOWRqst]/2;
BCmdMap:      NAT = ORD[DynaBusInterface.Cmd.MapRqst]/2;
BCmdRB:      NAT = ORD[DynaBusInterface.Cmd.RBRqst]/2;
BCmdWB:      NAT = ORD[DynaBusInterface.Cmd.WBRqst]/2;
BCmdWS:      NAT = ORD[DynaBusInterface.Cmd.WSRqst]/2;
Fault Code Defs
FaultMemAccess:    NAT = 0;
FaultIOAccess:    NAT = 1;
FaultBTimeOut:    NAT = 2;
Input Declarations
ASh:       NAT = ctx.Declare["ASh",     in];
AVM:       NAT = ctx.Declare["AVM",     in];
FBTIP:       NAT = ctx.Declare["FBTIP ",    in];
MyBFault:     NAT = ctx.Declare["MyBFault",   in];
NonFBTIP:     NAT = ctx.Declare["NonFBTIP",   in];
PAccessPerm:    NAT = ctx.Declare["PAccessPerm",   in];
PCmd:      NAT = ctx.Declare["PCmd",     in, NumPCmdBits];
PCWSEq:     NAT = ctx.Declare["PCWSEq",    in];
RamForP:     NAT = ctx.Declare["RamForP",    in];
RCamForP:     NAT = ctx.Declare["RCamForP",   in];
RPValid:     NAT = ctx.Declare["RPValid",    in];
TestCode:     NAT = ctx.Declare["TestCode",    in, 3];
TimeOut:     NAT = ctx.Declare["TimeOut",    in];
TopOfStack:    NAT = ctx.Declare["TopOfStack",   in, NumStackBits];
Reset:      NAT = ctx.Declare["Reset",     in];
Output Declarations
PC:  NATIF usePC THEN ctx.Declare["PC", outIn, NumPCBits] ELSE 0;
PCtlABusCmd:    NAT = ctx.Declare["PCtlABusCmd",   out, 4];
PCtlBCmd:     NAT = ctx.Declare["PCtlBCmd",    out, 4]; -- Xs
PCtlIdle:      NAT = ctx.Declare["PCtlIdle",     out];
PCtlCSCmd:     NAT = ctx.Declare["PCtlCSCmd",    out, 2];
PCtlDBusCmd:    NAT = ctx.Declare["PCtlDBusCmd",   out, 2];
PCtlEnCamSel:    NAT = ctx.Declare["PCtlEnCamSel",   out];
PCtlEnCamSelExt:   NAT = ctx.Declare["PCtlEnCamSelExt",  out];
PCtlFault:     NAT = ctx.Declare["PCtlFault",     out];
PCtlFaultCode:   NAT = ctx.Declare["PCtlFaultCode",   out, 2];
PCtlForceWordAddress: NAT = ctx.Declare["PCtlForceWordAddress", out];
PCtlPartFMch:    NAT = ctx.Declare["PCtlPartFMch",   out];
PCtlFrzVictim:   NAT = ctx.Declare["PCtlFrzVictim",   out];
PCtlLdFIFOSetFBTIP: NAT = ctx.Declare["PCtlLdFIFOSetFBTIP", out];
PCtlLdFlagsReg:   NAT = ctx.Declare["PCtlLdFlagsReg",   out];
PCtlLdRBufDataLo:  NAT = ctx.Declare["PCtlLdRBufDataLo",  out];
PCtlLdRBufDataHi:  NAT = ctx.Declare["PCtlLdRBufDataHi",  out];
PCtlLdRBufHeader:  NAT = ctx.Declare["PCtlLdRBufHeader",  out];
PCtlLdSnooperSetValid: NAT = ctx.Declare["PCtlLdSnooperSetValid", out];
PCtlPartVMch:   NAT = ctx.Declare["PCtlPartVMch",   out];
PCtlRdRam:     NAT = ctx.Declare["PCtlRdRam",    out];
PCtlRdRCam:    NAT = ctx.Declare["PCtlRdRCam",    out];
PCtlRdVCam:    NAT = ctx.Declare["PCtlRdVCam",    out];
PCtlReleaseP:    NAT = ctx.Declare["PCtlReleaseP",    out];
PCtlResetVictim:   NAT = ctx.Declare["PCtlResetVictim",   out];
PCtlRSCmd:     NAT = ctx.Declare["PCtlRSCmd",    out, 2];
PCtlSelBFC:    NAT = ctx.Declare["PCtlSelBFC",    out];
PCtlSelRplyData:   NAT = ctx.Declare["PCtlSelRplyData",   out];
PCtlSetNonFBTIP:   NAT = ctx.Declare["PCtlSetNonFBTIP",  out];
PCtlShftVictim:   NAT = ctx.Declare["PCtlShftVictim",   out];
PCtlWtMchVCam:   NAT = ctx.Declare["PCtlWtMchVCam",  out];
PCtlWtRam:     NAT = ctx.Declare["PCtlWtRam",    out];
Push:       NAT = ctx.Declare["Push",      out];
Stack:      NAT = ctx.Declare["Stack",    out, NumStackBits]; -- Xs
Useful micro procs
This corresponds to the ReadRCam command cycle
ReadRCam1: PROC [] = {
AddOut[PCtlRdRCam,  T];
AddOut[PCtlEnCamSel,  T];
AddOut[PCtlEnCamSelExt, F]};
This corresponds to the first cycle of RCam use
ReadRCam2: PROC [sCmd: NAT] = {
AddOut[PCtlRdRCam,  T];
AddOut[PCtlEnCamSel,  T];
AddOut[PCtlEnCamSelExt, F];
AddOut[PCtlCSCmd, sCmd] };
This corresponds to the second and third cycles of RCam use (note they are the same)
ReadRCam34: PROC [sCmd: NAT] = {
AddOut[PCtlCSCmd,   sCmd] };
This corresponds to the ReadVCam command cycle
ReadVCam1: PROC [sCmd: NAT] = {
AddOut[PCtlRdVCam,  T];
AddOut[PCtlEnCamSel,  T];
AddOut[PCtlEnCamSelExt, F]};
This corresponds to the first cycle of VCam use
ReadVCam2: PROC [sCmd: NAT] = {
AddOut[PCtlRdVCam,  T];
AddOut[PCtlEnCamSel,  T];
AddOut[PCtlEnCamSelExt, F];
AddOut[PCtlCSCmd,  sCmd]};
This corresponds to the second and third cycles of VCam use (note they are the same)
ReadVCam34: PROC [sCmd: NAT] = {
AddOut[PCtlCSCmd, sCmd]};
This corresponds to the ReadRam command cycle
ReadRam1: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
AddOut[PCtlRSCmd, sCmd];
AddOut[PCtlRdRam, T]};
This corresponds to the first cycle of Ram use (note that ReadRam2 must follow ReadRam1
ReadRam2: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
AddOut[PCtlRSCmd, sCmd];
IF drDBus = DBus THEN AddOut[PCtlDBusCmd, DBusRRLatch]};
This corresponds to the second cycle of Ram use
ReadRam3: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
IF drDBus = DBus THEN AddOut[PCtlDBusCmd, DBusRRLatch]};
This corresponds to the WriteRam command cycle
WriteRam1: PROC [sCmd: NAT, data: NAT] = {
AddOut[PCtlRSCmd, sCmd];
AddOut[PCtlWtRam, T]};
This corresponds to the first cycle of Ram use (note that WriteRam2 must follow ReadRam1
WriteRam2: PROC [sCmd: NAT, data: NAT] = {
AddOut[PCtlRSCmd, sCmd];
AddOut[PCtlDBusCmd, data]};
This corresponds to the second cycle of Ram use
WriteRam3: PROC [sCmd: NAT, data: NAT] = {
AddOut[PCtlDBusCmd, data]};
JmpState: PROC [dest: IO.ROPE] = {
SELECT dest FROM
StoreBTimeOutFaultPC,
StoreMemAccessFaultPC,
StoreIOAccessFaultPC => {
AddOut[PCtlABusCmd,   ABusIOFault];
AddOut[PCtlWtMchVCam,  T]};
IdlePC => {
AddOut[PCtlIdle,    T];
AddOut[PCtlLdRBufDataLo, T]};
ENDCASE;
IF usePC THEN AddOut[PC, StateIndex[dest]];
FSM.JmpState[ctx, dest]};
The microcode
IfState[NIL];
Stack bits are initialized to keep Rosemary happy
AddOut[Push,  T];
AddOut[Stack, FromRead];
JmpState[Init];
IfState[Init]; -- Test dispatching - djc
If[f: TestCode, v: 0, m: 6]; JmpState[IdlePC];    -- 0, 1
If[f: TestCode, v: 2, m: 6]; JmpState[TestReadRamPC];  -- 2, 3
If[f: TestCode, v: 4];  JmpState[TestReadRCamPC]; -- 4
If[f: TestCode, v: 5];  JmpState[TestReadVCamPC]; -- 5
If[f: TestCode, v: 6];  JmpState[TestShiftVictimPC]; -- 6
If[f: TestCode, v: 7];  JmpState[TestResetVictimPC]; -- 7
EndIf[];
IfState[IdlePC];
If[f: PCmd, v: 0, m: PCmdRead]; -- TRUE if less THAN PCmdRead=8
JmpState[IdlePC];
If[PCmd, PCmdRead];
If[AVM, T];
Hit: Everything is done automatically
JmpState[HandleMissPC];
If[AVM, F];
A miss: Do partial virtual match to find translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromRead];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdWrite];
If[AVM, T];
A hit: Check if shared bit is set; Wait for ASh to be available
JmpState[PStorePC];
If[AVM, F];
A miss: Do partial virtual match to find translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromWrite];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdCWS];
If[AVM, T];
A hit: Good, get the old value
AddOut[PCtlABusCmd, ABusIOOld];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS3PC];
If[AVM, F];
A miss: Do partial virtual match to find translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromCWS];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdIORead];
If[AVM, T];
A hit: Everything is done automatically
JmpState[IdlePC];
If[AVM, F];
A miss: Check if we have access permission; First match without flags
AddOut[PCtlPartFMch , T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromIORead];
JmpState[ChkPermPC];
EndIf[];
If[PCmd, PCmdIOWrite];
If[AVM, T];
A hit: Everything is done automatically
JmpState[IdlePC];
If[AVM, F];
A miss: Check if we have access permission; First match without flags
AddOut[PCtlPartFMch , T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromIOWrite];
JmpState[ChkPermPC];
EndIf[];
If[PCmd, PCmdBIOWrite, PCmd14];
This operation always misses: Load RqstBuf header with IO address; Send ArbRequest; Set NonFBTIP (continuation is the same as IOWrite)
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlBCmd, BCmdBIOW];
AddOut[PCtlABusCmd, ABusPAdd];
JmpState[PSReturn1PC];
If[PCmd, PCmdDeMap];
This operation always misses: Load RqstBuf header with IO address; Send ArbRequest; Set NonFBTIP (continuation is the same as IOWrite)
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlBCmd, BCmdDeMap];
AddOut[PCtlABusCmd, ABusPAdd];
JmpState[PSReturn1PC];
EndIf[];
IfState[ChkPermPC];
Wait virtual match w/o flags to complete, 1 of 3
JmpState[CP1PC];
IfState[CP1PC];
Wait virtual match w/o flags to complete, 2 of 3
JmpState[CP2PC];
IfState[CP2PC];
Wait virtual match w/o flags to complete, 3 of 3
JmpState[CP3PC];
IfState[CP3PC];
If[AVM, T];
Partial match successful: an IO access permission fault, store it and return
JmpState[StoreIOAccessFaultPC];
If[AVM, F];
A miss. Generate IO(Read/Write) Rqst packet: Load RqstBuf header with IO address; Load RqstBuf data with PData (doesn't hurt for read); Send ArbRqst; Set NonFBTIP; Return when transaction completes (same as PS)
AddOut[PCtlABusCmd, ABusPAdd];
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlDBusCmd, DBusPWtLatch];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
AddOut[PCtlSetNonFBTIP, T];
If[TopOfStack, FromIOWrite, 1]; -- assume only FromIORead, FromIOWrite possible - djc
AddOut[PCtlBCmd, BCmdIOW];
JmpState[PSReturn1PC];
If[TopOfStack, FromIORead, 1]; -- assume only FromIORead, FromIOWrite possible - djc
AddOut[PCtlBCmd, BCmdIOR];
JmpState[PSReturn1PC];
EndIf[];
EndIf[];
IfState[IOR2PC];
If[NonFBTIP, T]; And[TimeOut, F];
Wait for reply to come back
JmpState[IOR2PC];
If[NonFBTIP, T]; And[TimeOut, T];
A timeOut: Signal and store in the array (can be done after releasing processor)
JmpState[StoreBTimeOutFaultPC];
If[NonFBTIP, F]; And[MyBFault, T];
Reply came back with a fault, release processor and return
AddOut[PCtlFault, T];
AddOut[PCtlSelBFC, T];
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
If[NonFBTIP, F]; And[MyBFault, F];
Reply came back normally, release processor and return
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
EndIf[];
IfState[PCWSRetryPC];
Wait for AVM, 1 of 3: Don't need Ram value, just want to verify a hit
JmpState[PCWSR2PC];
IfState[PCWSR2PC];
Wait for AVM, 2 of 3
AddOut[PCtlABusCmd, ABusIOOld];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS3PC];
IfState[PCWS3PC];
Wait for AVM, 3 of 3: Read Ram to get the old value
ReadRam1[SCmdLVM];
JmpState[PCWS4PC];
IfState[PCWS4PC];
If[AVM, T];
A hit: Wait for PCWSEq, 1 of 3; (Can't let the processor go, sample value may be wrong)
ReadRam2[SCmdLVM];
JmpState[PCWS5PC];
If[AVM, F];
A miss: Do partial virtual match to find translation
ReadRam2[SCmdLVM];
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromCWS];
JmpState[HandleMissPC];
EndIf[];
IfState[PCWS5PC];
If[RamForP, T];
Wait for PCWSEq, 2 of 3: Compare old and sample; Put old in RqstBuf in case shared is set
AddOut[PCtlLdRBufDataHi, T];
ReadRam3[SCmdLVM];
JmpState[PCWS6PC];
If[RamForP, F];
Ratted! Just redo it: Read Ram to get the old value
ReadRam1[SCmdLVM];
JmpState[PCWS4PC];
EndIf[];
IfState[PCWS6PC];
Wait for PCWSEq, 3 of 3
JmpState[PCWS7PC];
IfState[PCWS7PC];
If[PCWSEq, T];
Read new value from the Ram, present IOAddress to VCam
AddOut[PCtlABusCmd, ABusIONew];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS8PC];
If[PCWSEq, F];
Not equal: Don't need to do anything
JmpState[IdlePC];
EndIf[];
IfState[PCWS8PC];
Read new value from the Ram, send ReadRam pulse
ReadRam1[SCmdLVM];
JmpState[PCWS9PC];
IfState[PCWS9PC];
Wait for data to appear in RRdLatch, 1 of 2
ReadRam2[SCmdLVM];
AddOut[PCtlABusCmd, ABusPAdd];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS10PC];
IfState[PCWS10PC];
If[RamForP, T];
Wait for data to appear in RRdLatch, 2 of 2: Start writing new data back; Load Rqst Buffer with new value in case shared bit is set
ReadRam3[SCmdLVM];
WriteRam1[SCmdLVM, DBusRRLatch];
JmpState[PCWS11PC];
If[RamForP, F];
Ratted! Re-read new value from scrtach; Present IOAddress to VCam
AddOut[PCtlABusCmd, ABusIONew];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS8PC];
EndIf[];
IfState[PCWS11PC];
Select RamReadLatch to go to the Ram, 1 of 2
Wait for Ash, 1 of 3
WriteRam2[SCmdLVM, DBusRRLatch];
JmpState[PCWS12PC];
IfState[PCWS12PC];
If[RamForP, T];
Select RamReadLatch to go to the Ram, 2 of 2; Wait for Ash, 2 of 3; Start RCam read in case of ASh
WriteRam3[SCmdLVM, DBusRRLatch];
AddOut[PCtlWtMchVCam, T];
AddOut[PCtlABusCmd, ABusPAdd];
JmpState[PCWS13PC];
If[RamForP, F];
Ratted! Re-read the new value from scratch; Present IOAddress to VCam
AddOut[PCtlABusCmd, ABusIONew];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS8PC];
EndIf[];
IfState[PCWS13PC];
Wait for Ash, 3 of 3; Read RCam, cycle 1
ReadRCam1[];
JmpState[PCWS14PC];
IfState[PCWS14PC];
If[ASh, T]; And[RCamForP, T];
Data is shared, generate CWSRqst; Read RCam to get real address, cycle 2
ReadRCam2[SCmdLVM];
JmpState[PCWS15PC];
If[ASh, T]; And[RCamForP, F];
Don't have RCam; Read RCam to get real address, cycle 1
ReadRCam1[];
JmpState[PCWS14PrimePC];
If[ASh, F];
Data is not shared, we are done
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
EndIf[];
IfState[PCWS14PrimePC];
If[RCamForP, T];
First, read RCam to get the real address, cycle 2
ReadRCam2[SCmdLVM];
JmpState[PCWS15PC];
If[RCamForP, F];
First, read RCam to get the real address, cycle 1
ReadRCam1[];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[PCWS15PC];
If[RCamForP, T];
Read RCam, cycle 3; We have the RCam, go to next cycle
ReadRCam34[SCmdLVM];
JmpState[PCWS16PC];
If[RCamForP, F];
Read RCam, cycle 1; We don't have the RCam, return to cycle 2
ReadRCam1[];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[PCWS16PC];
If[RCamForP, T];
Read RCam, cycle 4; RCam has been read; Send ArbRqst; Set NonFBTIP
AddOut[PCtlSetNonFBTIP, T];
ReadRCam34[SCmdLVM];
JmpState[PCWS17PC];
If[RCamForP, F];
Read RCam, cycle 1; We don't have the RCam, return to cycle 2
ReadRCam1[];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[PCWS17PC];
Load RqstBuf header with real address
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdCWS];
AddOut[PCtlABusCmd, ABusCam];
JmpState[PSReturn2PC];
IfState[PSRetryPC];
Wait for AVM, 1 of 3; Write Ram in case of a match
WriteRam1[SCmdLVM, DBusPWtLatch];
JmpState[PSR2PC];
IfState[PSR2PrimePC];
If[AVM, T];
Wait for time to pass
WriteRam2[SCmdLVM, DBusPWtLatch];
JmpState[PSR3PC];
If[AVM, F];
A miss: Do partial virtual match to find translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromWrite];
JmpState[HandleMissPC];
EndIf[];
IfState[PSR2PC];
Wait for AVM, 2 of 3
WriteRam2[SCmdLVM, DBusPWtLatch];
JmpState[PSR3PC];
IfState[PSR3PC];
If[RamForP, T];
Wait for AVM, 3 of 3
WriteRam3[SCmdLVM, DBusPWtLatch];
JmpState[PSR4PC];
If[RamForP, F];
Ratted! Just redo it; Write the Ram in case of a match
WriteRam1[SCmdLVM, DBusPWtLatch];
JmpState[PSR2PrimePC];
EndIf[];
IfState[PSR4PC];
If[AVM, T];
A hit: Check for shared bit; Wait for ASh to be available
JmpState[PStorePC];
If[AVM, F];
A miss: Do partial virtual match to find translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[Stack, FromWrite];
JmpState[HandleMissPC];
EndIf[];
IfState[PStorePC];
If[ASh, T];
Data is shared, generate WSRqst; Read RCam to get the real address
ReadRCam1[];
JmpState[PSRRCVM2PC];
If[ASh, F];
Data is not shared, everything is done automatically: Release processor
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
EndIf[];
IfState[PSRRCVM2PC];
If[RCamForP, T];
Read RCam, cycle 2: We have RCam, go to next cycle
ReadRCam2[SCmdLVM];
JmpState[PSRRCVM3PC];
If[RCamForP, F];
Read RCam, cycle 1: We don't have RCam, return to cycle 2
ReadRCam1[];
JmpState[PSRRCVM2PC];
EndIf[];
IfState[PSRRCVM3PC];
If[RCamForP, T];
Read RCam, cycle 3: We have RCam, go to next cycle
ReadRCam34[SCmdLVM];
JmpState[PSRRCVM4PC];
If[RCamForP, F];
Read RCam, cycle 1: We don't have RCam, return to cycle 2
ReadRCam1[];
JmpState[PSRRCVM2PC];
EndIf[];
IfState[PSRRCVM4PC];
If[RCamForP, T];
Read RCam, cycle 4: RCam has been read; Send ArbRqst; Set NonFBTIP
AddOut[PCtlSetNonFBTIP, T];
ReadRCam34[SCmdLVM];
JmpState[PSRCamReadyPC];
If[RCamForP, F];
Read RCam, cycle 1: We don't have RCam, return to cycle 2
ReadRCam1[];
JmpState[PSRRCVM2PC];
EndIf[];
IfState[PSRCamReadyPC];
Load Rqst buffer header with real address
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdWS];
AddOut[PCtlABusCmd, ABusCam];
JmpState[PSReturn2PC];
IfState[PSReturn1PC];
Blow one cycle to give NonFBTIP time to be set
JmpState[PSReturn2PC];
IfState[PSReturn2PC];
If[NonFBTIP, T]; And[TimeOut, F];
Wait for WSRply, IOWRply, IORRply, BIOWRply, DeMapRply
AddOut[PCtlSelRplyData, T];
JmpState[PSReturn2PC];
If[NonFBTIP, T]; And[TimeOut, T];
A timeOut: Signal and return
AddOut[PCtlSelRplyData, T];
JmpState[StoreBTimeOutFaultPC];
If[NonFBTIP, F]; And[MyBFault, T];
WSRply has come back with a fault, release processor and return
AddOut[PCtlFault, T];
AddOut[PCtlSelBFC, T];
AddOut[PCtlReleaseP, T];
AddOut[PCtlSelRplyData, T];
JmpState[IdlePC];
If[NonFBTIP, F]; And[MyBFault, F];
Reply has come back, release processor and return
AddOut[PCtlReleaseP, T];
AddOut[PCtlSelRplyData, T];
JmpState[IdlePC];
EndIf[];
IfState[HandleMissPC];
Wait for partial virtual match, 1 of 3: (Could begin the RCam read here at the expense of (~6) more lines) Freeze victim, Cycle 1 of 2
AddOut[PCtlFrzVictim, T];
JmpState[HM1PC];
Note: The index i in HMiPC refers to time, not cycle number
IfState[HM1PC];
Wait for partial virtual match, 2 of 3: Initiate RCam read in case partial match succeeds, Read RCam cycle 1; Freeze victim, Cycle 2 of 2
ReadRCam1[];
AddOut[PCtlFrzVictim, T];
JmpState[HM2PC];
IfState[HM2PC];
If[RCamForP, T];
Wait for partial virtual match, 3 of 3; Read RCam, cycle 2
ReadRCam2[SCmdLVM];
JmpState[HM3PPC];
If[RCamForP, F];
Wait for partial virtual match, 3 of 3; Don't have RCam, Read RCam, cycle 1
ReadRCam1[];
JmpState[HM3nPPC];
EndIf[];
IfState[HM3PPC];
If[AVM, T]; And[RCamForP, T];
Partial virtual match is successful; Read RCam, cycle 3
ReadRCam34[SCmdLVM];
JmpState[HMRRCVM4PC];
If[AVM, T]; And[RCamForP, F];
Partial virtual match is successful; Don't have RCam, Read RCam, cycle 1
ReadRCam1[];
JmpState[HM3nPPC];
If[AVM, F];
Read AId from the Ram, first do a match in the VCam. Note that this destroys the old contents of the vCamWtReg, which be restored automatically by the hardwired control when the MapRply comes back (see VCamInterlockCtl).
AddOut[PCtlABusCmd, ABusIOAId];
AddOut[PCtlWtMchVCam, T];
JmpState[HMnMPC];
EndIf[];
IfState[HMnMPC];
Read AId from Ram, cycle 1; Load RqstBuf with MapRqst|myId|PAdd; Set NonFBTIP
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdMap];
AddOut[PCtlABusCmd, ABusPAdd];
ReadRam1[SCmdLVM];
JmpState[HMnM11PC];
IfState[HMnM11PC];
Read AId from Ram, cycle 2; Wait for AId to appear in the RRdLatch, 1 of 1
ReadRam2[SCmdLVM];
JmpState[HMnM12PC];
IfState[HMnM12PC];
If[RamForP, T];
Load RBufLo with AId, RBufHi with garbage; Send ArbRqst
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
ReadRam3[SCmdLVM];
JmpState[HMnM3PC];
If[RamForP, F];
Ratted, didn't have Ram! Just redo it
ReadRam1[SCmdLVM];
JmpState[HMnM11PC];
EndIf[];
IfState[HMnM3PC];
Blow one cycle to let NonFBTIP get set
JmpState[HMnM4PC];
IfState[HMnM4PC];
If[NonFBTIP, T]; And[TimeOut, F];
Wait for MapRply to come back.
AddOut[PCtlCSCmd, SCmdVictim];
JmpState[HMnM4PC];
If[NonFBTIP, T]; And[TimeOut, T];
TimeOut : Signal and store the fault in the array
JmpState[StoreBTimeOutFaultPC];
If[NonFBTIP, F]; And[MyBFault, T];
MapCache fault: abort access
AddOut[PCtlFault, T];
AddOut[PCtlSelBFC, T];
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
If[NonFBTIP, F]; And[MyBFault, F];
Load Rqst buffer header with RealAddress; Read RCam using victim, cycle 1; Set CSCmd to select Victim so we can drive the cam (rcampage+vcamblock) onto the ABus (note that ReadRCam1 does not set the CSCmd).
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdRB];
AddOut[PCtlCSCmd, SCmdVictim];
AddOut[PCtlABusCmd, ABusCam];
ReadRCam1[];
JmpState[HMRRCVct2PC];
EndIf[];
For all jumps to this location except the one from HM2PC, we know that the AVM check will succeed since match is latched, and AVM was high earlier. Doing the check in all cases allows us to share this instruction, thereby eliminating waste.
IfState[HM3nPPC];
If[AVM, T]; And[RCamForP, T];
Partial virtual match is successful; Read RCam, cycle 2
ReadRCam2[SCmdLVM];
JmpState[HMRRCVM3PC];
If[AVM, T]; And[RCamForP, F];
Partial virtual match is successful; Didn't have RCam, Read RCam, cycle 1
ReadRCam1[];
JmpState[HM3nPPC];
If[AVM, F];
Read AId from the Ram, first find it in the VCam
AddOut[PCtlABusCmd, ABusIOAId];
AddOut[PCtlWtMchVCam, T];
JmpState[HMnMPC];
EndIf[];
IfState[HMRRCVM3PC];
If[RCamForP, T];
Read RCam, cycle 3
ReadRCam34[SCmdLVM];
JmpState[HMRRCVM4PC];
If[RCamForP, F];
Read RCam, cycle 1; Didn't have RCam, redo read
ReadRCam1[];
JmpState[HM3nPPC];
EndIf[];
IfState[HMRRCVM4PC];
If[RCamForP, T];
Read RCam, cycle 4; RCam has been read
ReadRCam34[SCmdLVM];
JmpState[HMRCamReadyPC];
If[RCamForP, F];
Read RCam, cycle 1; Didn't have RCam, redo read
ReadRCam1[];
JmpState[HM3nPPC];
EndIf[];
We've read RPage from the RCam successfully
IfState[HMRCamReadyPC];
If[PAccessPerm, T];
Load RqstBuf header with RealAddress; Load FlagsReg; Read RCam using victim, cycle 1.
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdRB];
AddOut[PCtlABusCmd, ABusCam];
AddOut[PCtlLdFlagsReg, T];
ReadRCam1[];
JmpState[HMRRCVct2PC];
If[PAccessPerm, F];
Fault: Signal and store in the array (can be done after releasing processor)
JmpState[StoreMemAccessFaultPC];
EndIf[];
IfState[HMRRCVct2PC];
If[RCamForP, T];
Read RCam using victim, cycle 2
ReadRCam2[SCmdVictim];
JmpState[HMRRCVct3PC];
If[RCamForP, F];
Read RCam, cycle 1; Didn't have RCam, return to cycle 2
ReadRCam1[];
JmpState[HMRRCVct2PC];
EndIf[];
IfState[HMRRCVct3PC];
If[RCamForP, T];
Read RCam using victim, cycle 3
ReadRCam34[SCmdVictim];
JmpState[HMRRCVct4PC];
If[RCamForP, F];
Read RCam, cycle 1; Didn't have RCam, return to cycle 2
ReadRCam1[];
JmpState[HMRRCVct2PC];
EndIf[];
IfState[HMRRCVct4PC];
If[RCamForP, T];
Read RCam using victim, cycle 4
ReadRCam34[SCmdVictim];
JmpState[HMReadRamPC];
If[RCamForP, F];
Read RCam, cycle 1; Didn't have RCam, return to cycle 2
ReadRCam1[];
JmpState[HMRRCVct2PC];
EndIf[];
IfState[HMReadRamPC];
ABus ← VictimAddress (note ABus ← AToDPipe Reg automatically); Load Snooper in case of FlushBlock; Set snooper valid to begin snooping;
ReadRam1[SCmdVictim, NoDBus];
AddOut[PCtlABusCmd, ABusRCam];
AddOut[PCtlLdSnooperSetValid, T];
JmpState[HMRR2PC];
IfState[HMRR2PC];
RqstBufLo ← AToDPipe; RqstBufHi ← garbage; ReadRam cycle 2
ReadRam2[SCmdVictim, NoDBus];
AddOut[PCtlDBusCmd, DBusABus];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
JmpState[HMRR3PC];
IfState[HMRR3PC];
If[RPValid, T]; And[RamForP, T];
Read Ram, cycle 3; LoadFIFOIfAOw; Generate FBRqst
ReadRam3[SCmdVictim, NoDBus];
AddOut[PCtlLdFIFOSetFBTIP, T]; -- Ld FIFO If AOw - external gating
AddOut[PCtlBCmd, BCmdFB];
AddOut[PCtlABusCmd, ABusRCam];
JmpState[HMRR4PC];
If[RPValid, T]; And[RamForP, F];
Redo Ram Read; Also redrive victim address onto ABus
ReadRam1[SCmdVictim, NoDBus];
AddOut[PCtlABusCmd, ABusRCam];
JmpState[HMRR2PC];
If[RPValid, F];
Victim is not valid, don't flush it.
Send RBRqst; Set NonFBTIP;
AddOut[PCtlSetNonFBTIP, T];
JmpState[HMReturn1PC];
EndIf[];
IfState[HMRR4PC];
Send RBRqst; Set NonFBTIP;
AddOut[PCtlSetNonFBTIP, T];
JmpState[HMReturn1PC];
IfState[HMReturn1PC];
Wait a cycle to let NonFBTIP get set; ABus←RealAddress to load Snooper on MyRBRqst
AddOut[PCtlABusCmd, ABusRqstBuf];
JmpState[HMReturn2PC];
IfState[HMReturn2PC];
If[NonFBTIP, T]; And[TimeOut, F];
Wait for RBRply; ABus←RealAddress to load Snooper on MyRBRqst
AddOut[PCtlABusCmd, ABusRqstBuf];
AddOut[PCtlSelRplyData, T];
JmpState[HMReturn2PC];
If[NonFBTIP, T]; And[TimeOut, T];
TimeOut: Signal and store the fault in the array
AddOut[PCtlSelRplyData, T];
JmpState[StoreBTimeOutFaultPC];
If[NonFBTIP, F]; And[MyBFault, T];
Reply has come back with a fault, release processor and return
AddOut[PCtlFault, T];
AddOut[PCtlSelBFC, T];
AddOut[PCtlReleaseP, T];
AddOut[PCtlSelRplyData, T];
JmpState[IdlePC]; -- check that fault code gets written automatically; if not, just do it in ucode by copying one of the store fault routines
If[NonFBTIP, F]; And[MyBFault, F];
AddOut[PCtlShftVictim, T];
JmpState[HMReturn3PC];
EndIf[];
IfState[HMReturn3PC];
Produce the pulse to write the VCam and Flags (recall that VCamWtReg may have been overwritten with the address of IOAID).
AddOut[PCtlWtMchVCam, T];
AddOut[PCtlABusCmd, ABusPAdd];
If[TopOfStack, FromRead];
Release processor and go to idle
AddOut[PCtlReleaseP, T];
AddOut[PCtlSelRplyData, T];
JmpState[IdlePC];
If[TopOfStack, FromWrite];
Wait two cycles because we can't use the VCam to do a match yet
JmpState[HMReturn4PC];
If[f: TopOfStack, v: FromCWS, m: FromCWS]; -- TRUE if >= FromCWS=2
Wait two cycles because we can't use the VCam to do a match yet
JmpState[HMReturn4PC];
EndIf[];
IfState[HMReturn4PC];
Wait one cycle because we can't use the VCam to do a match yet
JmpState[HMReturn5PC];
IfState[HMReturn5PC];
AddOut[PCtlWtMchVCam, T];
If[f: TopOfStack, v: FromWrite, m: FromCWS]; -- TRUE if < FromCWS=2
Do a Match to check if address is in array
JmpState[PSRetryPC];
If[f: TopOfStack, v: FromCWS, m: FromCWS]; -- TRUE if >= FromCWS=2
Do a Match to check if address is in array
JmpState[PCWSRetryPC];
EndIf[];
IfState[StoreMemAccessFaultPC];
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultMemAccess];
JmpState[SMAF2PC];
IfState[SMAF2PC];
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultMemAccess];
JmpState[SMAF3PC];
IfState[SMAF3PC];
If[RamForP, T];
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
AddOut[PCtlFault, T];
AddOut[PCtlFaultCode, FaultMemAccess];
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
If[RamForP, F];
Ratted! Redo the access
AddOut[PCtlDBusCmd, DBusABus];
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultMemAccess];
JmpState[SMAF2PC];
EndIf[];
IfState[StoreBTimeOutFaultPC];
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultBTimeOut];
JmpState[SBTOF2PC];
IfState[SBTOF2PC];
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultBTimeOut];
JmpState[SBTOF3PC];
IfState[SBTOF3PC];
If[RamForP, T];
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
AddOut[PCtlFault, T];
AddOut[PCtlFaultCode, FaultBTimeOut];
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
If[RamForP, F];
Ratted! Redo the access
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultBTimeOut];
JmpState[SBTOF2PC];
EndIf[];
IfState[StoreIOAccessFaultPC];
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultIOAccess];
JmpState[SIOAF2PC];
IfState[SIOAF2PC];
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultIOAccess];
JmpState[SIOAF3PC];
IfState[SIOAF3PC];
If[RamForP, T];
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
AddOut[PCtlFault, T];
AddOut[PCtlFaultCode, FaultIOAccess];
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
If[RamForP, F];
Ratted! Redo the access
AddOut[PCtlDBusCmd, DBusABus];
WriteRam1[SCmdLVM, DBusABus];
AddOut[PCtlABusCmd, ABusFault+FaultIOAccess];
JmpState[SIOAF2PC];
EndIf[];
Here begins the tests subroutines. They cannot be executed during normal operations. They are reached only by the mean of a TestCode forced by the DebugBus. It is assumed that the DynaBus is stopped during these operations.
IfState[TestReadRamPC];
AddOut[PCtlForceWordAddress, T];
ReadRam1[SCmdVictim];
JmpState[TRR2PC];
IfState[TRR2PC];
AddOut[PCtlForceWordAddress, T];
ReadRam2[SCmdVictim];
JmpState[TRR3PC];
IfState[TRR3PC];
AddOut[PCtlForceWordAddress, T];
ReadRam3[SCmdVictim];
AddOut[PCtlLdRBufDataHi, T];
JmpState[IdlePC];
IfState[TestReadRCamPC];
Read RCam using Victim, cycle 1
ReadRCam1[];
JmpState[TRRC2PC];
IfState[TRRC2PC];
Read RCam using Victim, cycle 2
ReadRCam2[SCmdVictim];
JmpState[TRRC3PC];
IfState[TRRC3PC];
Read RCam using Victim, cycle 3
ReadRCam34[SCmdVictim];
JmpState[TRRC4PC];
IfState[TRRC4PC];
Read RCam using Victim, cycle 4
ReadRCam34[SCmdVictim];
JmpState[TRRC5PC];
IfState[TRRC5PC];
Put Victim into the ABus to DBus pipe (automatic) through the ABus
AddOut[PCtlABusCmd, ABusRCam];
JmpState[TRRC6PC];
IfState[TRRC6PC];
Load RBufDataLo with the content of the RCam
AddOut[PCtlDBusCmd, DBusABus];
AddOut[PCtlLdRBufDataHi, T];
JmpState[IdlePC];
IfState[TestReadVCamPC];
Read VCam using Victim, cycle 1
ReadVCam1[SCmdVictim];
JmpState[TRVC2PC];
IfState[TRVC2PC];
Read VCam using Victim, cycle 2
ReadVCam2[SCmdVictim];
JmpState[TRVC3PC];
IfState[TRVC3PC];
Read VCam using Victim, cycle 3
ReadVCam34[SCmdVictim];
JmpState[TRVC4PC];
IfState[TRVC4PC];
Read VCam using Victim, cycle 4
ReadVCam34[SCmdVictim];
JmpState[TRVC5PC];
IfState[TRVC5PC];
Put Victim into the ABus to DBus pipe (automatic) through the ABus
AddOut[PCtlABusCmd, ABusVCam];
JmpState[TRVC6PC];
IfState[TRVC6PC];
Load RBufDataLo with the content of the VCam
AddOut[PCtlDBusCmd, DBusABus];
AddOut[PCtlLdRBufDataHi, T];
JmpState[IdlePC];
IfState[TestShiftVictimPC];
The victim is assumed to be waiting at some place
AddOut[PCtlShftVictim, T];
JmpState[TSV2PC];
IfState[TSV2PC];
The victim may point to a place where it wants to get out of
Force it to stay there. Cycle 1 of 2
AddOut[PCtlFrzVictim, T];
JmpState[TSV3PC];
IfState[TSV3PC];
The victim may point to a place where it wants to get out of
Force it to stay there. Cycle 2 of 2
AddOut[PCtlFrzVictim, T];
JmpState[IdlePC];
IfState[TestResetVictimPC];
Force the victim to point at the initial place. Cycle 1 of 2
AddOut[PCtlResetVictim, T];
JmpState[TRV2PC];
IfState[TRV2PC];
Force the victim to point at the initial place. Cycle 2 of 2
The victim will not get out now that the used bit has been cleared
AddOut[PCtlResetVictim, T];
JmpState[IdlePC];
fsm ← FSM.Finish[ctx];
fsm.outInAll ← NOT usePC;
fsm.register ← reg;
ct ← FSM.CodeMachine[fsm, impl]};
END.