BuildFSM:
PUBLIC
PROC
RETURNS [fsm:
FSM.FSMData] = {
machName: IO.ROPE ← "SCPmCode";
Declare the finite state machine generation procs
ctx: FSM.Context ← FSM.Create[machName];
IfReset: PROC = {FSM.IfReset [ctx]};
IfState: PROC[s: IO.ROPE] = {FSM.IfState [ctx,s]};
If: PROC[f, v: NAT, m: NAT ← FSM.default] = {FSM.If [ctx,f,v,m]};
And: PROC[f, v: NAT, m: NAT ← FSM.default] = {FSM.And [ctx,f,v,m]};
AddOut: PROC[f, v: NAT, m: NAT ← FSM.default] = {FSM.AddOut [ctx,f,v,m]};
EndIf: PROC = {FSM.EndIf [ctx]};
Declare value constants and field sizes
T: NAT = 1;
F: NAT = 0;
retAddr: NAT ← 0;
NextRetAddr: PROC RETURNS [ra: NAT] = {ra ← retAddr; retAddr ← retAddr+1};
FromRead: NAT = NextRetAddr[];
FromIORead: NAT = FromRead;
FromWrite: NAT = NextRetAddr[];
FromIOWrite: NAT = FromWrite;
FromCWS: NAT = NextRetAddr[];
MaxStack: NAT = NextRetAddr[];
NumStackBits: NAT = BitOps.NBits[MaxStack-1];
PCmdNoOp: NAT = 7;
PCmdRead: NAT = 8;
PCmdWrite: NAT = 9;
PCmdCWS: NAT = 10;
PCmdDeMap: NAT = 11;
PCmdIORead: NAT = 12;
PCmdIOWrite: NAT = 13;
PCmdBIOWrite: NAT = 15;
NumPCmdBits: NAT = 4;
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;
DBusNoOp: NAT = 0;
DBusPWtLatch: NAT = 1;
DBusRRLatch: NAT = 2;
DBusABus: NAT = 3;
SCmdNoOp: NAT = 0;
SCmdLRM: NAT = 1;
SCmdLVM: NAT = 2;
SCmdVictim: NAT = 3;
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;
FaultMemAccess: NAT = 0;
FaultIOAccess: NAT = 1;
FaultBTimeOut: NAT = 2;
Input Declarations
AOw: NAT = ctx.Declare["AOw", in];
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];
TimeOut: NAT = ctx.Declare["TimeOut", in];
Stack: NAT = ctx.Declare["Stack", in, NumStackBits];
Reset: NAT = ctx.Declare["Reset", in];
Output Declarations
PCtlABusCmd: NAT = ctx.Declare["PCtlABusCmd", out, 4];
PCtlBCmd: NAT = ctx.Declare["PCtlBCmd", out, 4];
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, 3];
PCtlFlagsForB: NAT = ctx.Declare["PCtlFlagsForB", out];
PCtlPartFMch: NAT = ctx.Declare["PCtlPartFMch", out];
PCtlFrzVictim: NAT = ctx.Declare["PCtlFrzVictim", out];
PCtlLdFIFO: NAT = ctx.Declare["PCtlLdFIFO", out];
PCtlLdRBufDataLo: NAT = ctx.Declare["PCtlLdRBufDataLo", out];
PCtlLdRBufDataHi: NAT = ctx.Declare["PCtlLdRBufDataHi", out];
PCtlLdRBufHeader: NAT = ctx.Declare["PCtlLdRBufHeader", out];
PCtlLdSnooper: NAT = ctx.Declare["PCtlLdSnooper", 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];
PCtlRSCmd: NAT = ctx.Declare["PCtlRSCmd", out, 2];
PCtlSelBFC: NAT = ctx.Declare["PCtlSelBFC", out];
PCtlSelRplyData: NAT = ctx.Declare["PCtlSelRplyData", out];
PCtlSetFBTIP: NAT = ctx.Declare["PCtlSetFBTIP", out];
PCtlSetNonFBTIP: NAT = ctx.Declare["PCtlSetNonFBTIP", out];
PCtlSetSnooperValid: NAT = ctx.Declare["PCtlSetSnooperValid", out];
PCtlShftVictim: NAT = ctx.Declare["PCtlShftVictim", out];
PCtlWtMchVCam: NAT = ctx.Declare["PCtlWtMchVCam", out];
PCtlWtRam: NAT = ctx.Declare["PCtlWtRam", out];
NxtStack: NAT = ctx.Declare["NxtStack", out, NumStackBits];
Push: NAT = ctx.Declare["Push", out];
State Declaratons
ChkPermPC: IO.ROPE = "ChkPermPC";
CP1PC: IO.ROPE = "CP1PC";
CP2PC: IO.ROPE = "CP2PC";
CP3PC: IO.ROPE = "CP3PC";
HandleMissPC: IO.ROPE = "HandleMissPC";
HM1PC: IO.ROPE = "HM1PC";
HM2PC: IO.ROPE = "HM2PC";
HM3PPC: IO.ROPE = "HM3PPC";
HM3nPPC: IO.ROPE = "HM3nPPC";
HM3nRPC: IO.ROPE = "HM3nRPC";
HMnMPC: IO.ROPE = "HMnMPC";
HMnM11PC: IO.ROPE = "HMnM11PC";
HMnM12PC: IO.ROPE = "HMnM12PC";
HMnM2PC: IO.ROPE = "HMnM2PC";
HMnM3PC: IO.ROPE = "HMnM3PC";
HMnM4PC: IO.ROPE = "HMnM4PC";
HMRCamReadyPC: IO.ROPE = "HMRCamReadyPC";
HMReadRamPC: IO.ROPE = "HMReadRamPC";
HMReturn1PC: IO.ROPE = "HMReturn1PC";
HMReturn2PC: IO.ROPE = "HMReturn2PC";
HMRR2PC: IO.ROPE = "HMRR2PC";
HMRR3PC: IO.ROPE = "HMRR3PC";
HMRR4PC: IO.ROPE = "HMRR4PC";
HMRR5PC: IO.ROPE = "HMRR5PC";
HMRR6PC: IO.ROPE = "HMRR6PC";
HMRRCVct2PC: IO.ROPE = "HMRRCVct2PC";
HMRRCVct3PC: IO.ROPE = "HMRRCVct3PC";
HMRRCVct4PC: IO.ROPE = "HMRRCVct4PC";
HMRRCVM2PC: IO.ROPE = "HMRRCVM2PC";
HMRRCVM3PC: IO.ROPE = "HMRRCVM3PC";
HMRRCVM4PC: IO.ROPE = "HMRRCVM4PC";
IdlePC: IO.ROPE = "IdlePC";
Init: IO.ROPE = "Init";
IOR2PC: IO.ROPE = "IOR2PC";
IOWritePC: IO.ROPE = "IOWritePC";
PCWS3PC: IO.ROPE = "PCWS3PC";
PCWS4PC: IO.ROPE = "PCWS4PC";
PCWS5PC: IO.ROPE = "PCWS5PC";
PCWS6PC: IO.ROPE = "PCWS6PC";
PCWS7PC: IO.ROPE = "PCWS7PC";
PCWS8PC: IO.ROPE = "PCWS8PC";
PCWS9PC: IO.ROPE = "PCWS9PC";
PCWS10PC: IO.ROPE = "PCWS10PC";
PCWS11PC: IO.ROPE = "PCWS11PC";
PCWS12PC: IO.ROPE = "PCWS12PC";
PCWS13PC: IO.ROPE = "PCWS13PC";
PCWS14PC: IO.ROPE = "PCWS14PC";
PCWS14PrimePC: IO.ROPE = "PCWS14PrimePC";
PCWS15PC: IO.ROPE = "PCWS15PC";
PCWS16PC: IO.ROPE = "PCWS16PC";
PCWS17PC: IO.ROPE = "PCWS17PC";
PCWSR2PC: IO.ROPE = "PCWSR2PC";
PCWSRetryPC: IO.ROPE = "PCWSRetryPC";
PSR2PC: IO.ROPE = "PSR2PC";
PSR2PrimePC: IO.ROPE = "PSR2PrimePC";
PSR3PC: IO.ROPE = "PSR3PC";
PSR4PC: IO.ROPE = "PSR4PC";
PSRetryPC: IO.ROPE = "PSRetryPC";
PSRetryPrimePC: IO.ROPE = "PSRetryPrimePC";
PSReturn1PC: IO.ROPE = "PSReturn1PC";
PSReturn2PC: IO.ROPE = "PSReturn2PC";
PSRCamReadyPC: IO.ROPE = "PSRCamReadyPC";
PSRRCVM2PC: IO.ROPE = "PSRRCVM2PC";
PSRRCVM3PC: IO.ROPE = "PSRRCVM3PC";
PSRRCVM4PC: IO.ROPE = "PSRRCVM4PC";
PStorePC: IO.ROPE = "PStorePC";
SBTOF2PC: IO.ROPE = "SBTOF2PC";
SBTOF3PC: IO.ROPE = "SBTOF3PC";
SIOAF2PC: IO.ROPE = "SIOAF2PC";
SIOAF3PC: IO.ROPE = "SIOAF3PC";
SMAF2PC: IO.ROPE = "SMAF2PC";
SMAF3PC: IO.ROPE = "SMAF3PC";
StoreBTimeOutFaultPC: IO.ROPE = "StoreBTimeOutFaultPC";
StoreMemAccessFaultPC: IO.ROPE = "StoreMemAccessFaultPC";
StoreIOAccessFaultPC: IO.ROPE = "StoreIOAccessFaultPC";
Useful micro procs
ReadRCam1:
PROC [sCmd:
NAT] = {
AddOut[PCtlRdRCam, T];
AddOut[PCtlEnCamSel, T];
AddOut[PCtlEnCamSelExt, F]};
ReadRCam2:
PROC [sCmd:
NAT] = {
AddOut[PCtlRdRCam, T];
AddOut[PCtlEnCamSel, T];
AddOut[PCtlEnCamSelExt, F];
AddOut[PCtlCSCmd, sCmd] };
ReadRCam34:
PROC [sCmd:
NAT] = {
AddOut[PCtlCSCmd, sCmd] };
This corresponds to the 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
ReadRam2:
PROC [sCmd:
NAT, drDBus: {DBus, NoDBus} ← DBus] = {
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]};
WriteRam1:
PROC [sCmd:
NAT, data:
NAT] = {
AddOut[PCtlRSCmd, sCmd];
AddOut[PCtlWtRam, T]};
WriteRam2:
PROC [sCmd:
NAT, data:
NAT] = {
AddOut[PCtlRSCmd, sCmd];
AddOut[PCtlDBusCmd, data]};
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];
AddOut[PCtlDBusCmd, DBusPWtLatch]};
ENDCASE;
FSM.JmpState[ctx, dest]};
The microcode
IfReset[];
Stack bits are initialized to keep Rosemary happy
AddOut[Push, T];
AddOut[NxtStack, FromRead];
JmpState[Init];
IfState[Init];
JmpState[IdlePC]; -- Initiate Reset sequence: (empty for now)
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];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromRead];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdWrite];
If[
AVM, T];
Hit : Check for shared
Wait for ASh to be available
JmpState[PStorePC];
If[
AVM, F];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromWrite];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdCWS];
If[
AVM, T];
Hit : Good, get the old value
AddOut[PCtlABusCmd, ABusIOOld];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS3PC];
If[
AVM, F];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromCWS];
JmpState[HandleMissPC ];
EndIf[];
If[PCmd, PCmdIORead];
If[
AVM, T];
Hit : Everything is done automaticly
JmpState[IdlePC];
If[
AVM, F];
Miss : Check for access permission.
First match without flags
AddOut[PCtlPartFMch , T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromIORead];
JmpState[ChkPermPC];
EndIf[];
If[PCmd, PCmdIOWrite];
If[
AVM, T];
Hit : Everything is done automaticly
JmpState[IdlePC];
If[
AVM, F];
Miss : Check for access permission.
First match without flags
AddOut[PCtlPartFMch , T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromIOWrite];
JmpState[ChkPermPC];
EndIf[];
If[PCmd, PCmdBIOWrite];
Always Misses
Load Rqst buffer header with IO address
Rqst to arbiter, remember with NonFBTIP
continuation is the same as IOWrite
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlBCmd, BCmdBIOW];
AddOut[PCtlABusCmd, ABusPAdd];
JmpState[PSReturn1PC];
If[PCmd, PCmdDeMap];
Always Misses
Load Rqst buffer header with IO address
Rqst to arbiter, remember with 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 virtual match is successful
This an IO access permission fault, store it and return
JmpState[StoreIOAccessFaultPC];
If[
AVM, F];
Miss : Generate IO(Read/Write)Rqst packet.
Load Rqst buffer header with IO address
Load data parts with PData (doesn't hurt for read)
Rqst to arbiter, remember with NonFBTIP
return when transaction is completed, same as PS
AddOut[PCtlABusCmd, ABusPAdd];
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlDBusCmd, DBusPWtLatch];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
AddOut[PCtlSetNonFBTIP, T];
If[Stack, FromIORead];
AddOut[PCtlBCmd, BCmdIOR];
JmpState[PSReturn1PC];
If[Stack, FromIOWrite];
AddOut[PCtlBCmd, BCmdIOW];
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];
timeOut : Signal and store in the array (can be done after having released processor)
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];
JmpState[IdlePC];
If[NonFBTIP, F]; And[MyBFault, F];
reply has come back, release processor and return
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
EndIf[];
IfState[PCWSRetryPC];
Wait for AVM, 1 of 3
We don't need to read the Ram, we just want to verify that the value is there.
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 the Ram to get the old value
ReadRam1[SCmdLVM];
JmpState[PCWS4PC];
IfState[
PCWS4PC];
If[
AVM, T];
Hit : Wait for the time to go
Wait for PCWSEq, 1 of 3
Cannot let the processor go : Sample value may be wrong
ReadRam2[SCmdLVM];
JmpState[PCWS5PC];
If[
AVM, F];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
ReadRam2[SCmdLVM];
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromCWS];
JmpState[HandleMissPC];
EndIf[];
IfState[
PCWS5PC];
If[RamForP, T];
go ahead and compare old and sample
Wait for PCWSEq, 2 of 3
Put the old value in the Rqst Buffer in case the data is shared
AddOut[PCtlLdRBufDataHi, T];
ReadRam3[SCmdLVM];
JmpState[PCWS6PC];
If[RamForP, F];
Ratted! Just redo it
Read the 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 the new value from the Ram, present IOAddress to VCam
AddOut[PCtlABusCmd, ABusIONew];
AddOut[PCtlWtMchVCam, T];
JmpState[PCWS8PC];
If[PCWSEq, F];
Fail: Nothing to be done
JmpState[IdlePC];
EndIf[];
IfState[
PCWS8PC];
Read the 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
Begin to write the new data back to the array
Load Rqst Buffer with new value in case of shared data
ReadRam3[SCmdLVM];
WriteRam1[SCmdLVM, DBusRRLatch];
JmpState[PCWS11PC];
If[RamForP, F];
Ratted! Reread the new value from scrtach
Read the new value from the Ram, 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
Begin to read the RCam in case of ASh
WriteRam3[SCmdLVM, DBusRRLatch];
AddOut[PCtlWtMchVCam, T];
AddOut[PCtlABusCmd, ABusPAdd];
JmpState[PCWS13PC];
If[RamForP, F];
Ratted! Reread the new value from scratch
Read the new value from the Ram, 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 [SCmdLVM];
JmpState[PCWS14PC];
IfState[
PCWS14PC];
If[ASh, T]; And[RCamForP, T];
Data is shared, generate CWSRqst
First, read RCam to get the real address, cycle 2
ReadRCam2[SCmdLVM];
JmpState[PCWS15PC];
If[ASh, T]; And[RCamForP, F];
Data is shared, generate CWSRqst
First, read RCam to get the real address, cycle 1
ReadRCam1[SCmdLVM];
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[SCmdLVM];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[
PCWS15PC];
If[RCamForP, T];
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
JmpState[PCWS16PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[
PCWS16PC];
If[RCamForP, T];
Read RCam, cycle 4
bus is quiet: RCam is read
Rqst to arbiter, remember with NonFBTIP
AddOut[PCtlSetNonFBTIP, T];
ReadRCam34[SCmdLVM];
JmpState[PCWS17PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[PCWS14PrimePC];
EndIf[];
IfState[
PCWS17PC];
Load Rqst buffer header with real address
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdCWS];
AddOut[PCtlABusCmd, ABusCam];
JmpState[PSReturn2PC];
IfState[PSRetryPC];
Wait for AVM, 1 of 3
Write the Ram in case of a match
WriteRam1[SCmdLVM, DBusPWtLatch];
JmpState[PSR2PC];
IfState[PSR2PrimePC];
If[
AVM, T];
Wait for time to go on
WriteRam2[SCmdLVM, DBusPWtLatch];
JmpState[PSR3PC];
If[
AVM, F];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, 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];
Hit : Check for shared
Wait for ASh to be available
JmpState[PStorePC];
If[
AVM, F];
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
AddOut[PCtlPartVMch, T];
AddOut[PCtlWtMchVCam, T];
AddOut[Push, T];
AddOut[NxtStack, FromWrite];
JmpState[HandleMissPC];
EndIf[];
IfState[PStorePC];
If[ASh, T];
Data is shared, generate WSRqst
First, read RCam to get the real address
ReadRCam1[SCmdLVM];
JmpState[PSRRCVM2PC];
If[ASh, F];
Data is not shared, Every thing is automatic
Release processor
AddOut[PCtlReleaseP, T];
JmpState[IdlePC];
EndIf[];
IfState[
PSRRCVM2PC];
If[RCamForP, T];
Read RCam, cycle 2
bus is quiet: go to next cycle
ReadRCam2[SCmdLVM];
JmpState[PSRRCVM3PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[PSRRCVM2PC];
EndIf[];
IfState[
PSRRCVM3PC];
If[RCamForP, T];
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
JmpState[PSRRCVM4PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[PSRRCVM2PC];
EndIf[];
IfState[
PSRRCVM4PC];
If[RCamForP, T];
Read RCam, cycle 4
bus is quiet: RCam is read
Rqst to arbiter, remember with NonFBTIP
AddOut[PCtlSetNonFBTIP, T];
ReadRCam34[SCmdLVM];
JmpState[PSRCamReadyPC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
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];
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 Partial virtual match to complete, 1 of 3
Could begin the RCam read at the expense of more (about 6 lines) microcode
Freeze victim to keep a warm place for RBRply. Should be 2 cycles long. Cycle 1 of 2
AddOut[PCtlFrzVictim, T];
JmpState[HM1PC];
IfState[
HM1PC];
Wait Partial virtual match to complete, 2 of 3
Initiate RCam read in case of a match
Read RCam, cycle 1
Freeze victim. Cycle 2 of 2
ReadRCam1[SCmdLVM];
AddOut[PCtlFrzVictim, T];
IfState[
HM2PC];
If[RCamForP, T];
Wait Partial virtual match to complete, 3 of 3
continue the RCam read in case of match
Read RCam, cycle 2
ReadRCam2[SCmdLVM];
JmpState[HM3PPC];
If[RCamForP, F];
Wait Partial virtual match to complete, 3 of 3
Read aborted by the bus side, redo it
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
JmpState[HM3nPPC];
EndIf[];
IfState[
HM3PPC];
If[
AVM, T]; And[RCamForP, T];
Partial virtual match is successful
bus is quiet, go to last cycle of Read RCam
Read RCam, cycle 3
ReadRCam34[SCmdLVM];
JmpState[HMRRCVM4PC];
If[
AVM, T]; And[RCamForP, F];
Partial virtual match is successful
bus is busy: return to cycle 2
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
JmpState[HMRRCVM2PC];
If[
AVM, F];
Read AId from the Ram, first find it in the VCam
AddOut[PCtlABusCmd, ABusIOAId];
AddOut[PCtlWtMchVCam, T];
JmpState[HMnMPC];
EndIf[];
IfState[HMnMPC];
Read AId from the Ram, cycle 1
Load output buffer with MapRqst|myId|PAdd
remember with NonFBTIP
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdMap];
AddOut[PCtlABusCmd, ABusPAdd];
ReadRam1[SCmdLVM];
JmpState[HMnM11PC];
IfState[HMnM11PC];
Read AId from the Ram, cycle 2
Wait for AId to appear in the RRdLatch, 1 of 1
ReadRam2[SCmdLVM];
JmpState[HMnM12PC];
IfState[HMnM12PC];
If[RamForP, T];
Load lower data field with AId
Load upper data field with garbage
Request to the arbiter
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
ReadRam3[SCmdLVM];
JmpState[HMnM3PC];
If[RamForP, F];
Ratted! Just redo it
Read the Ram to get the AId value
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[PCtlFlagsForB, T];
JmpState[HMnM4PC];
If[NonFBTIP, T]; And[TimeOut, T];
Time out : 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 read address
Read RCam using victim, cycle 1
Warning : Same as HMRCamReadyPC
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdRB];
AddOut[PCtlABusCmd, ABusCam];
ReadRCam1[SCmdVictim];
JmpState[HMRRCVct2PC];
EndIf[];
IfState[HM3nPPC];
If[
AVM, T]; And[RCamForP, T];
Partial virtual match is successful
bus is quiet, go to next cycle (#3) of Read RCam
Read RCam, cycle 2
ReadRCam2[SCmdLVM];
JmpState[HMRRCVM3PC];
If[
AVM, T]; And[RCamForP, F];
Partial virtual match is successful
bus is busy: return to cycle 2
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
JmpState[HMRRCVM2PC];
If[
AVM, F];
Read AId from the Ram, first find it in the VCam
AddOut[PCtlABusCmd, ABusIOAId];
AddOut[PCtlWtMchVCam, T];
JmpState[HMnMPC];
EndIf[];
IfState[
HMRRCVM2PC];
If[RCamForP, T];
Read RCam, cycle 2
bus is quiet: go to next cycle
ReadRCam2[SCmdLVM];
JmpState[HMRRCVM3PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[HMRRCVM2PC];
EndIf[];
IfState[
HMRRCVM3PC];
If[RCamForP, T];
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
JmpState[HMRRCVM4PC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[HMRRCVM2PC];
EndIf[];
IfState[
HMRRCVM4PC];
If[RCamForP, T];
Read RCam, cycle 4
bus is quiet: RCam is read
ReadRCam34[SCmdLVM];
JmpState[HMRCamReadyPC];
If[RCamForP, F];
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
JmpState[HMRRCVM2PC];
EndIf[];
IfState[HMRCamReadyPC];
If[PAccessPerm, T];
Load Rqst buffer header with read address
Read RCam using victim, cycle 1
AddOut[PCtlLdRBufHeader, T];
AddOut[PCtlBCmd, BCmdRB];
AddOut[PCtlABusCmd, ABusCam];
ReadRCam1[SCmdVictim];
JmpState[HMRRCVct2PC];
If[PAccessPerm, F];
Fault : Signal and store in the array (can be done after having released the 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
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
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
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
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
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
JmpState[HMRRCVct2PC];
EndIf[];
IfState[HMReadRamPC];
Put victim address into rqst buffer (next cycle) and snooper in case of a Flush
Set snooper valid to begin snooping right now
ReadRam1[SCmdVictim, NoDBus];
AddOut[PCtlABusCmd, ABusRCam];
AddOut[PCtlLdSnooper, T];
AddOut[PCtlSetSnooperValid, T];
JmpState[HMRR2PC];
IfState[
HMRR2PC];
Wait for AOw. Read Ram, cycle 2
Load Buffer upper data field with garbage
ReadRam2[SCmdVictim, NoDBus];
AddOut[PCtlDBusCmd, DBusABus];
AddOut[PCtlLdRBufDataLo, T];
AddOut[PCtlLdRBufDataHi, T];
JmpState[HMRR3PC];
IfState[
HMRR3PC];
If[RamForP, T];
Wait for AOw. Read Ram, cycle 3
ReadRam3[SCmdVictim, NoDBus];
JmpState[HMRR4PC];
If[RamForP, F];
Redo the access including reloading the bridge between the ABus and the DBus
ReadRam1[SCmdVictim, NoDBus];
AddOut[PCtlABusCmd, ABusRCam];
JmpState[HMRR2PC];
EndIf[];
IfState[
HMRR4PC];
Wait for AOw. Read Ram, cycle 4
JmpState[HMRR5PC];
RPValid is on the ABus only while the Victim address is being read. Thus think about doing the RPValid check there. Also, it looks as though the ABus is not driven properly when the victim address is read.
IfState[
HMRR5PC];
-- Can AOw=F and RPValid=F ??? djc
If[AOw, T]; And[RPValid, T];
Generate FBRqst
AddOut[PCtlBCmd, BCmdFB];
AddOut[PCtlABusCmd, ABusRCam];
AddOut[PCtlSetFBTIP, T];
AddOut[PCtlLdFIFO, T];
JmpState[HMRR6PC];
If[AOw, F];
Send RBRqst, remember with NonFBTIP
AddOut[PCtlSetNonFBTIP, T];
JmpState[HMReturn1PC];
If[RPValid, F];
Victim is not valid, do not flush it
Send RBRqst, remember with NonFBTIP
This test could be done before with some care. To be optimized if this case turn out to be more than 0.00000001% of the time
AddOut[PCtlSetNonFBTIP, T];
JmpState[HMReturn1PC];
EndIf[];
IfState[
HMRR6PC];
Send RBRqst, remember with NonFBTIP
Put the address being read on the ABus to load the snooper when the FBRqst comes back
AddOut[PCtlSetNonFBTIP, T];
AddOut[PCtlABusCmd, ABusRqstBuf];
JmpState[HMReturn1PC];
IfState[HMReturn1PC];
Blow one cycle to let NonFBTIP be set
JmpState[HMReturn2PC];
IfState[HMReturn2PC];
If[NonFBTIP, T]; And[TimeOut, F];
Wait for rply to come back
Put the address being read on the ABus to load the snooper when the FBRqst comes back
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];
If[NonFBTIP, F]; And[MyBFault, F];
AddOut[PCtlShftVictim, T];
If[Stack, FromRead];
Come from read: nothing else to do, just release the processor and victim logic.
AddOut[PCtlReleaseP, T];
AddOut[PCtlSelRplyData, T];
JmpState[IdlePC];
If[Stack, FromWrite];
Try again, match VCam with Paddress
AddOut[PCtlWtMchVCam, T];
JmpState[PSRetryPC];
If[Stack, FromCWS];
Try again, match VCam with Paddress
AddOut[PCtlWtMchVCam, T];
JmpState[PCWSRetryPC];
EndIf[];
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[];
fsm ← FSM.Finish[ctx];
fsm.register ← none};