SCPmCodeImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created: Douady, Sindhu April 10, 1987 12:50:16 pm PDT
Pradeep Sindhu July 22, 1987 3:19:08 pm PDT
Cesar Douady May 13, 1987 3:09:46 pm PDT
Contains the Processor-side microcode. It models only the combinatorial part. The complete model is in PCtl.sch.
The assumption about speed is that signals can go through the combinatorial part in just under one clock cycle, so that inputs need to come directly from flops, and outputs need to go directly to flops, with no intervening logic. This structure means 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
Core, CoreClasses, CoreCreate, CoreFlat, DynaBusInterface, IO, Ports, SCUtils, Rosemary, RosemaryUser, SCPmCode, TerminalIO;
SCPmCodeImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, CoreFlat, IO, Ports, Rosemary, SCUtils, TerminalIO
EXPORTS SCPmCode
~ BEGIN OPEN SCPmCode;
NumPCmdBits: NAT = 4;
MaxNumSignals: NAT = 100;
Xs: NAT = LAST[NAT];
ToBeDefined: NAT = Xs;
IndexType: TYPE = {Label, ReturnAddress, IOAddr};
Index: ARRAY IndexType OF NATALL [0];
ChkPermPC: NAT = Next[Label];
CP1PC: NAT = Next[Label];
CP2PC: NAT = Next[Label];
CP3PC: NAT = Next[Label];
HandleMissPC: NAT = Next[Label];
HM1PC: NAT = Next[Label];
HM2PC: NAT = Next[Label];
HM3PPC: NAT = Next[Label];
HM3nPPC: NAT = Next[Label];
HM3nRPC: NAT = Next[Label];
HMnMPC: NAT = Next[Label];
HMnM11PC: NAT = Next[Label];
HMnM12PC: NAT = Next[Label];
HMnM2PC: NAT = Next[Label];
HMnM3PC: NAT = Next[Label];
HMnM4PC: NAT = Next[Label];
HMRCamReadyPC: NAT = Next[Label];
HMReadRamPC: NAT = Next[Label];
HMReturn1PC: NAT = Next[Label];
HMReturn2PC: NAT = Next[Label];
HMRR2PC: NAT = Next[Label];
HMRR3PC: NAT = Next[Label];
HMRR4PC: NAT = Next[Label];
HMRR5PC: NAT = Next[Label];
HMRR6PC: NAT = Next[Label];
HMRRCVct2PC: NAT = Next[Label];
HMRRCVct3PC: NAT = Next[Label];
HMRRCVct4PC: NAT = Next[Label];
HMRRCVM2PC: NAT = Next[Label];
HMRRCVM3PC: NAT = Next[Label];
HMRRCVM4PC: NAT = Next[Label];
IdlePC: NAT = Next[Label];
IOR2PC: NAT = Next[Label];
IOWritePC: NAT = Next[Label];
PCWS3PC: NAT = Next[Label];
PCWS4PC: NAT = Next[Label];
PCWS5PC: NAT = Next[Label];
PCWS6PC: NAT = Next[Label];
PCWS7PC: NAT = Next[Label];
PCWS8PC: NAT = Next[Label];
PCWS9PC: NAT = Next[Label];
PCWS10PC: NAT = Next[Label];
PCWS11PC: NAT = Next[Label];
PCWS12PC: NAT = Next[Label];
PCWS13PC: NAT = Next[Label];
PCWS14PC: NAT = Next[Label];
PCWS14PrimePC: NAT = Next[Label];
PCWS15PC: NAT = Next[Label];
PCWS16PC: NAT = Next[Label];
PCWS17PC: NAT = Next[Label];
PCWSR2PC: NAT = Next[Label];
PCWSRetryPC: NAT = Next[Label];
PSR2PC: NAT = Next[Label];
PSR2PrimePC: NAT = Next[Label];
PSR3PC: NAT = Next[Label];
PSR4PC: NAT = Next[Label];
PSRetryPC: NAT = Next[Label];
PSRetryPrimePC: NAT = Next[Label];
PSReturn1PC: NAT = Next[Label];
PSReturn2PC: NAT = Next[Label];
PSRCamReadyPC: NAT = Next[Label];
PSRRCVM2PC: NAT = Next[Label];
PSRRCVM3PC: NAT = Next[Label];
PSRRCVM4PC: NAT = Next[Label];
PStorePC: NAT = Next[Label];
ResetPC: NAT = Next[Label];
SBTOF2PC: NAT = Next[Label];
SBTOF3PC: NAT = Next[Label];
SIOAF2PC: NAT = Next[Label];
SIOAF3PC: NAT = Next[Label];
SMAF2PC: NAT = Next[Label];
SMAF3PC: NAT = Next[Label];
StoreBTimeOutFaultPC: NAT = Next[Label];
StoreMemAccessFaultPC: NAT = Next[Label];
StoreIOAccessFaultPC: NAT = Next[Label];
MaxPC: NAT = Next[Label];
FromRead: NAT = Next[ReturnAddress];
FromIORead: NAT = FromRead;
FromWrite: NAT = Next[ReturnAddress];
FromIOWrite: NAT = FromWrite;
FromCWS: NAT = Next[ReturnAddress];
MaxStack: NAT = Next[ReturnAddress];
ABusPAdd: NAT = 0;
ABusRqstBuf: NAT = 1;
ABusVCam: NAT = 4;
  -- opCode 5 is forbidden by the hardware
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;
PCmdNoOp: NAT = 7;
PCmdRead: NAT = 8;
PCmdWrite: NAT = 9;
PCmdCWS: NAT = 10;
PCmdDeMap: NAT = 11;
PCmdIORead: NAT = 12;
PCmdIOWrite: NAT = 13;
PCmdBIOWrite: NAT = 15;
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;
NumPCBits: PUBLIC NAT ← 1+SCUtils.Log2[MaxPC-1];
NumStackBits: PUBLIC NAT ← 1+SCUtils.Log2[MaxStack-1];
SignalType: TYPE = {Input, InputXAllowed, Output, Power};
Signals: TYPE = REF SignalsRec;
SignalsRec: TYPE = RECORD [
SEQUENCE size: NAT OF RECORD [
name: ROPENIL,
size: NAT ← 0,
st: SignalType,
default: Level ← X,
defaultS: NAT ← Xs,
index: NAT ← Xs
]
];
The signals:
The declaration below simply creates signals, putting signal foo's characteristics in signals[foo]
signals: Signals ← NEW [SignalsRec[MaxNumSignals]];
numSignals: NAT ← 0;
AOw: NAT = Declare["AOw", X, Input];
ASh: NAT = Declare["ASh", X, Input];
AVM: NAT = Declare["AVM", X, Input];
FBTIP: NAT = Declare["FBTIP", X, Input];
MyBFault: NAT = Declare["MyBFault", X, Input];
NonFBTIP: NAT = Declare["NonFBTIP", X, Input];
PAccessPermission: NAT = Declare["PAccessPermission", X, Input];
PCmd: NAT = DeclareS["PCmd", NumPCmdBits, Xs, Input];
PCWSEq: NAT = Declare["PCWSEq", X, InputXAllowed];
RamForP: NAT = Declare["RamForP", X, Input];
RCamForP: NAT = Declare["RCamForP", X, Input];
RPValid: NAT = Declare["RPValid", X, Input];
TimeOut: NAT = Declare["TimeOut", X, Input];
PC: NAT = DeclareS["PC", NumPCBits, Xs, Input];
Stack: NAT = DeclareS["Stack", NumStackBits, Xs, InputXAllowed];
Reset: NAT = Declare["Reset", X, Input];
PCtlABusCmd: NAT = DeclareS["PCtlABusCmd", 4, ABusPAdd, Output];
PCtlBCmd: NAT = DeclareS["PCtlBCmd", 4, Xs, Output];
PCtlBusy: NAT = Declare["PCtlBusy", H, Output];
PCtlCSCmd: NAT = DeclareS["PCtlCSCmd", 2, SCmdNoOp, Output];
PCtlDBusCmd: NAT = DeclareS["PCtlDBusCmd", 2, DBusNoOp, Output];
PCtlEnCamSel: NAT = Declare["PCtlEnCamSel", L, Output];
PCtlEnCamSelExt: NAT = Declare["PCtlEnCamSelExt", L, Output];
PCtlFault: NAT = Declare["PCtlFault", L, Output];
PCtlFaultCode: NAT = DeclareS["PCtlFaultCode", 3, 0, Output];
PCtlFlagsForB: NAT = Declare["PCtlFlagsForB", L, Output];
PCtlPartFMch: NAT = Declare["PCtlPartFMch", L, Output];
PCtlFrzVictim: NAT = Declare["PCtlFrzVictim", L, Output];
PCtlLdFIFO: NAT = Declare["PCtlLdFIFO", L, Output];
PCtlLdRBufDataLo: NAT = Declare["PCtlLdRBufDataLo", L, Output];
PCtlLdRBufDataHi: NAT = Declare["PCtlLdRBufDataHi", L, Output];
PCtlLdRBufHeader: NAT = Declare["PCtlLdRBufHeader", L, Output];
PCtlLdSnooper: NAT = Declare["PCtlLdSnooper", L, Output];
PCtlPartVMch: NAT = Declare["PCtlPartVMch", L, Output];
PCtlRdRam: NAT = Declare["PCtlRdRam", L, Output];
PCtlRdRCam: NAT = Declare["PCtlRdRCam", L, Output];
PCtlRdVCam: NAT = Declare["PCtlRdVCam", L, Output];
PCtlReleaseP: NAT = Declare["PCtlReleaseP", L, Output];
PCtlRSCmd: NAT = DeclareS["PCtlRSCmd", 2, SCmdNoOp, Output];
PCtlSelBFC: NAT = Declare["PCtlSelBFC", L, Output];
PCtlSelRplyData: NAT = Declare["PCtlSelRplyData", L, Output];
PCtlSetFBTIP: NAT = Declare["PCtlSetFBTIP", L, Output];
PCtlSetNonFBTIP: NAT = Declare["PCtlSetNonFBTIP", L, Output];
PCtlSetSnooperValid: NAT = Declare["PCtlSetSnooperValid", L, Output];
PCtlShftVictim: NAT = Declare["PCtlShftVictim", L, Output];
PCtlWtMchVCam: NAT = Declare["PCtlWtMchVCam", L, Output];
PCtlWtRam: NAT = Declare["PCtlWtRam", L, Output];
NxtPC: NAT = DeclareS["NxtPC", NumPCBits, Xs, Output];
NxtStack: NAT = DeclareS["NxtStack", NumStackBits, Xs, Output];
Push: NAT = Declare["Push", L, Output];
Vdd: NAT = Declare["Vdd", X, Power];
Gnd: NAT = Declare["Gnd", X, Power];
Public Procs
Create: PUBLIC PROC [] RETURNS [ct: CellType] = {
nameList: LIST OF CoreCreate.WRNIL;
FOR i: NAT IN [0..numSignals) DO
IF signals[i].name=NIL THEN LOOP;
IF signals[i].size=0
THEN nameList ← CONS[signals[i].name, nameList]
ELSE nameList ← CONS[CoreCreate.Seq[signals[i].name, signals[i].size], nameList]
ENDLOOP;
ct ← CoreClasses.CreateUnspecified[public: CoreCreate.WireList[nameList, pmCodeName, NIL]];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: pmCodeName];
[] ← CoreFlat.CellTypeCutLabels[ct, "Logic"];
FOR i: NAT IN [0..numSignals) DO
IF signals[i].name=NIL THEN LOOP;
signals[i].index ← Ports.PortIndex[ct.public, signals[i].name];
ENDLOOP;
FOR i: NAT IN [0..numSignals) DO
SwitchType: TYPE = RECORD [BOOL, SignalType];
switch: SwitchType ← [signals[i].size=0, signals[i].st];
IF signals[i].name=NIL THEN LOOP;
SELECT switch FROM
[TRUE, Input] => [] ← Ports.InitPorts[ct, l, none, signals[i].name]; 
[TRUE, InputXAllowed] => [] ← Ports.InitPorts[ct, l, none, signals[i].name]; 
[TRUE, Output] => [] ← Ports.InitPorts[ct, l, drive, signals[i].name];
[TRUE, Power] => [] ← Ports.InitPorts[ct, b, none, signals[i].name];
[FALSE, Input] => [] ← Ports.InitPorts[ct, ls, none, signals[i].name];
[FALSE, InputXAllowed] => [] ← Ports.InitPorts[ct, ls, none, signals[i].name];
[FALSE, Output] => [] ← Ports.InitPorts[ct, ls, drive, signals[i].name];
ENDCASE => ERROR;
ENDLOOP;
};
Init: Rosemary.InitProc = {
--PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [stateAny: REF ANY ← NIL]--
};
Simple: Rosemary.EvalProc = {
--PROC [p: Ports.Port, stateAny: REF ANY]--
XInInputs: PROC [] RETURNS [BOOLFALSE] = {
PrintName: PROC [name: ROPE] = {
TerminalIO.PutF["*** Input %g is an X\n", IO.rope[name]];
};
FOR i: NAT IN [0..numSignals) DO
IF signals[i].name=NIL OR signals[i].st#Input THEN LOOP;
IF signals[i].size=0
THEN {IF p[signals[i].index].l=X THEN {PrintName[signals[i].name]; RETURN[TRUE]}}
ELSE {IF XInLS[p[signals[i].index].ls] THEN {PrintName[signals[i].name]; RETURN[TRUE]}}
ENDLOOP;
};
OutputsToX: PROC [] = {
FOR i: NAT IN [0..numSignals) DO
IF signals[i].name=NIL OR signals[i].st#Output THEN LOOP;
IF signals[i].size=0
THEN p[signals[i].index].l ← X
ELSE Ports.SetLS[p[signals[i].index].ls, X]
ENDLOOP;
};
OutputsToDefault: PROC [] = {
FOR i: NAT IN [0..numSignals) DO
IF signals[i].name=NIL OR signals[i].st#Output THEN LOOP;
IF signals[i].size=0
THEN p[signals[i].index].l ← signals[i].default
ELSE Ports.LCToLS[signals[i].defaultS, p[signals[i].index].ls]
ENDLOOP;
};
v: PROC [ix: NAT] RETURNS [BOOL] = {
RETURN[p[signals[ix].index].l=H]
};
vs: PROC [ix: NAT] RETURNS [NAT] = {
RETURN[Ports.LSToLC[p[signals[ix].index].ls]]
};
s: PROC [ix: NAT, l: Level] = {
p[signals[ix].index].l ← l
};
ss: PROC [ix: NAT, c: CARD] = {
IF c=Xs
THEN Ports.SetLS[p[signals[ix].index].ls, X]
ELSE Ports.LCToLS[c, p[signals[ix].index].ls];
};
ReadRCam1: PROC [sCmd: NAT] = {
s[PCtlRdRCam, H];
s[PCtlEnCamSel, H];
s[PCtlEnCamSelExt, L];
};
ReadRCam2: PROC [sCmd: NAT] = {
s[PCtlRdRCam, H];
s[PCtlEnCamSel, H];
s[PCtlEnCamSelExt, L];
ss[PCtlCSCmd, sCmd];
};
ReadRCam34: PROC [sCmd: NAT] = {
ss[PCtlCSCmd, sCmd];
};
This corresponds to the command cycle
ReadRam1: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
ss[PCtlRSCmd, sCmd];
s[PCtlRdRam, H];
};
This corresponds to the first cycle of Ram use
ReadRam2: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
ss[PCtlRSCmd, sCmd];
IF drDBus = DBus THEN ss[PCtlDBusCmd, DBusRRLatch];
};
This corresponds to the second cycle of Ram use
ReadRam3: PROC [sCmd: NAT, drDBus: {DBus, NoDBus} ← DBus] = {
IF drDBus = DBus THEN ss[PCtlDBusCmd, DBusRRLatch];
};
WriteRam1: PROC [sCmd: NAT, data: NAT] = {
ss[PCtlRSCmd, sCmd];
s[PCtlWtRam, H];
};
WriteRam2: PROC [sCmd: NAT, data: NAT] = {
ss[PCtlRSCmd, sCmd];
ss[PCtlDBusCmd, data];
};
WriteRam3: PROC [sCmd: NAT, data: NAT] = {
ss[PCtlDBusCmd, data];
};
Jmp: PROC [dest: NAT] = {
IF dest=StoreBTimeOutFaultPC OR
dest=StoreMemAccessFaultPC OR
dest=StoreIOAccessFaultPC THEN {
ss[PCtlABusCmd, ABusIOFault];
s[PCtlWtMchVCam, H];
};
IF dest=IdlePC THEN {
s[PCtlBusy, L];
s[PCtlLdRBufDataLo, H];
ss[PCtlDBusCmd, DBusPWtLatch];
};
ss[NxtPC, dest];
};
OutputsToDefault[];
The microcode
IF v[Reset]
Stack bits are initialized to keep Rosemary happy
THEN {s[Push, H]; ss[NxtStack, FromRead]; Jmp[ResetPC];}
ELSE {
IF XInInputs[] THEN {OutputsToX[]; RETURN};
SELECT vs[PC] FROM
= ResetPC  => {
IF TRUE THEN {
Initiate Reset sequence: (empty for now)
Jmp[IdlePC];
};
};
= IdlePC  => {
SELECT vs[PCmd] FROM
<= PCmdNoOp => {
Wait for something to happen
Jmp[IdlePC];
};
= PCmdRead => {
IF v[AVM] THEN {
Hit: Everything is done automatically
Jmp[IdlePC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
s[PCtlPartVMch , H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromRead];
Jmp[HandleMissPC];
};
};
= PCmdWrite => {
IF v[AVM] THEN {
Hit : Check for shared
Wait for ASh to be available
Jmp[PStorePC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
s[PCtlPartVMch, H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromWrite];
Jmp[HandleMissPC];
};
};
= PCmdCWS => {
IF v[AVM] THEN {
Hit : Good, get the old value
ss[PCtlABusCmd, ABusIOOld];
s[PCtlWtMchVCam, H];
Jmp[PCWS3PC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
s[PCtlPartVMch , H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromCWS];
Jmp[HandleMissPC];
};
};
= PCmdIORead => {
IF v[AVM] THEN {
Hit : Everything is done automaticly
Jmp[IdlePC];
};
IF NOT v[AVM] THEN {
Miss : Check for access permission.
First match without flags
s[PCtlPartFMch , H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromIORead];
Jmp[ChkPermPC];
};
};
= PCmdIOWrite => {
IF v[AVM] THEN {
Hit : Everything is done automaticly
Jmp[IdlePC];
};
IF NOT v[AVM] THEN {
Miss : Check for access permission.
First match without flags
s[PCtlPartFMch , H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromIOWrite];
Jmp[ChkPermPC];
};
};
= PCmdBIOWrite => {
IF TRUE THEN {
Always Misses
Load Rqst buffer header with IO address
Rqst to arbiter, remember with NonFBTIP
continuation is the same as IOWrite
s[PCtlLdRBufHeader, H];
s[PCtlSetNonFBTIP, H];
ss[PCtlBCmd, BCmdBIOW];
ss[PCtlABusCmd, ABusPAdd];
Jmp[PSReturn1PC];
};
};
= PCmdDeMap => {
IF TRUE THEN {
Always Misses
Load Rqst buffer header with IO address
Rqst to arbiter, remember with NonFBTIP
continuation is the same as IOWrite
s[PCtlLdRBufHeader, H];
s[PCtlSetNonFBTIP, H];
ss[PCtlBCmd, BCmdDeMap];
ss[PCtlABusCmd, ABusPAdd];
Jmp[PSReturn1PC];
};
};
ENDCASE => ERROR;
};
= ChkPermPC => {
IF TRUE THEN {
Wait virtual match w/o flags to complete, 1 of 3
Jmp[CP1PC];
};
};
= CP1PC => {
IF TRUE THEN {
Wait virtual match w/o flags to complete, 2 of 3
Jmp[CP2PC];
};
};
= CP2PC => {
IF TRUE THEN {
Wait virtual match w/o flags to complete, 3 of 3
Jmp[CP3PC];
};
};
= CP3PC => {
IF v[AVM] THEN {
Partial virtual match is successful
This an IO access permission fault, store it and return
Jmp[StoreIOAccessFaultPC];
};
IF NOT v[AVM] THEN {
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
ss[PCtlABusCmd, ABusPAdd];
s[PCtlLdRBufHeader, H];
ss[PCtlDBusCmd, DBusPWtLatch];
s[PCtlLdRBufDataLo, H];
s[PCtlLdRBufDataHi, H];
s[PCtlSetNonFBTIP, H];
Jmp[PSReturn1PC];
SELECT vs[Stack] FROM
=FromIORead => {
Generate IOReadRqst
ss[PCtlBCmd, BCmdIOR];
};
= FromIOWrite => {
Generate IOWriteRqst
ss[PCtlBCmd, BCmdIOW];
};
ENDCASE => ERROR;
};
};
= IOR2PC => {
IF v[NonFBTIP] AND NOT v[TimeOut] THEN {
Wait for reply to come back
Jmp[IOR2PC];
};
IF v[NonFBTIP] AND v[TimeOut] THEN {
timeOut : Signal and store in the array (can be done after having released the processor)
Jmp[StoreBTimeOutFaultPC];
};
IF NOT v[NonFBTIP] AND v[MyBFault] THEN {
reply has come back with a fault, release processor and return
s[PCtlFault, H];
s[PCtlSelBFC, H];
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
IF NOT v[NonFBTIP] AND NOT v[MyBFault] THEN {
reply has come back, release processor and return
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
};
= PCWSRetryPC => {
IF TRUE THEN {
Wait for AVM, 1 of 3
We don't need to read the Ram, we just want to verify that the value is there.
Jmp[PCWSR2PC];
};
};
= PCWSR2PC => {
IF TRUE THEN {
Wait for AVM, 2 of 3
ss[PCtlABusCmd, ABusIOOld];
s[PCtlWtMchVCam, H];
Jmp[PCWS3PC];
};
};
= PCWS3PC => {
IF TRUE THEN {
Wait for AVM, 3 of 3
Read the Ram to get the old value
ReadRam1[SCmdLVM];
Jmp[PCWS4PC];
};
};
= PCWS4PC => {
IF v[AVM] THEN {
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];
Jmp[PCWS5PC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
ReadRam2[SCmdLVM];
s[PCtlPartVMch, H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromCWS];
Jmp[HandleMissPC];
};
};
= PCWS5PC => {
IF v[RamForP] THEN {
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
s[PCtlLdRBufDataHi, H];
ReadRam3[SCmdLVM];
Jmp[PCWS6PC];
};
IF NOT v[RamForP] THEN {
Ratted! Just redo it
Read the Ram to get the old value
ReadRam1[SCmdLVM];
Jmp[PCWS4PC];
};
};
= PCWS6PC => {
IF TRUE THEN {
Wait for PCWSEq, 3 of 3
Jmp[PCWS7PC];
};
};
= PCWS7PC => {
IF v[PCWSEq] THEN {
Read the new value from the Ram, present IOAddress to VCam
ss[PCtlABusCmd, ABusIONew];
s[PCtlWtMchVCam, H];
Jmp[PCWS8PC];
};
IF NOT v[PCWSEq] THEN {
Fail : Nothing to be done
Jmp[IdlePC];
};
};
= PCWS8PC => {
IF TRUE THEN {
Read the new value from the Ram, Send ReadRam pulse
ReadRam1[SCmdLVM];
Jmp[PCWS9PC];
};
};
= PCWS9PC => {
IF TRUE THEN {
Wait for Data to appear in RRdLatch, 1 of 2
ReadRam2[SCmdLVM];
ss[PCtlABusCmd, ABusPAdd];
s[PCtlWtMchVCam, H];
Jmp[PCWS10PC];
};
};
= PCWS10PC => {
IF v[RamForP] THEN {
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];
Jmp[PCWS11PC];
};
IF NOT v[RamForP] THEN {
Ratted! Reread the new value from scrtach
Read the new value from the Ram, present IOAddress to VCam
ss[PCtlABusCmd, ABusIONew];
s[PCtlWtMchVCam, H];
Jmp[PCWS8PC];
};
};
= PCWS11PC => {
IF TRUE THEN {
Select RamReadLatch to go to the Ram, 1 of 2
Wait for Ash, 1 of 3
WriteRam2[SCmdLVM, DBusRRLatch];
Jmp[PCWS12PC];
};
};
= PCWS12PC => {
IF v[RamForP] THEN {
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];
s[PCtlWtMchVCam, H];
ss[PCtlABusCmd, ABusPAdd];
Jmp[PCWS13PC];
};
IF NOT v[RamForP] THEN {
Ratted! Reread the new value from scratch
Read the new value from the Ram, present IOAddress to VCam
ss[PCtlABusCmd, ABusIONew];
s[PCtlWtMchVCam, H];
Jmp[PCWS8PC];
};
};
= PCWS13PC => {
IF TRUE THEN {
Wait for Ash, 3 of 3
Read RCam, cycle 1
ReadRCam1 [SCmdLVM];
Jmp[PCWS14PC];
};
};
= PCWS14PC => {
IF v[ASh] AND v[RCamForP] THEN {
Data is shared, generate CWSRqst
First, read RCam to get the real address, cycle 2
ReadRCam2[SCmdLVM];
Jmp[PCWS15PC];
};
IF v[ASh] AND NOT v[RCamForP] THEN {
Data is shared, generate CWSRqst
First, read RCam to get the real address, cycle 1
ReadRCam1[SCmdLVM];
Jmp[PCWS14PrimePC];
};
IF NOT v[ASh] THEN {
Data is not shared, We are done
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
};
= PCWS14PrimePC => {
IF v[RCamForP] THEN {
First, read RCam to get the real address, cycle 2
ReadRCam2[SCmdLVM];
Jmp[PCWS15PC];
};
IF NOT v[RCamForP] THEN {
First, read RCam to get the real address, cycle 1
ReadRCam1[SCmdLVM];
Jmp[PCWS14PrimePC];
};
};
= PCWS15PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
Jmp[PCWS16PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[PCWS14PrimePC];
};
};
= PCWS16PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 4
bus is quiet: RCam is read
Rqst to arbiter, remember with NonFBTIP
s[PCtlSetNonFBTIP, H];
ReadRCam34[SCmdLVM];
Jmp[PCWS17PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[PCWS14PrimePC];
};
};
= PCWS17PC => {
IF TRUE THEN {
Load Rqst buffer header with real address
s[PCtlLdRBufHeader, H];
ss[PCtlBCmd, BCmdCWS];
ss[PCtlABusCmd, ABusCam];
Jmp[PSReturn2PC];
};
};
= PSRetryPC => {
IF TRUE THEN {
Wait for AVM, 1 of 3
Write the Ram in case of a match
WriteRam1[SCmdLVM, DBusPWtLatch];
Jmp[PSR2PC];
};
};
= PSR2PrimePC => {
IF v[AVM] THEN {
Wait for time to go on
WriteRam2[SCmdLVM, DBusPWtLatch];
Jmp[PSR3PC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
s[PCtlPartVMch, H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromWrite];
Jmp[HandleMissPC];
};
};
= PSR2PC => {
IF TRUE THEN {
Wait for AVM, 2 of 3
WriteRam2[SCmdLVM, DBusPWtLatch];
Jmp[PSR3PC];
};
};
= PSR3PC => {
IF v[RamForP] THEN {
Wait for AVM, 3 of 3
WriteRam3[SCmdLVM, DBusPWtLatch];
Jmp[PSR4PC];
};
IF NOT v[RamForP] THEN {
Ratted! Just redo it
Write the Ram in case of a match
WriteRam1[SCmdLVM, DBusPWtLatch];
Jmp[PSR2PrimePC];
};
};
= PSR4PC => {
IF v[AVM] THEN {
Hit : Check for shared
Wait for ASh to be available
Jmp[PStorePC];
};
IF NOT v[AVM] THEN {
Miss : Begin HandleMiss operations.
First, Partial match to find the address translation
s[PCtlPartVMch, H];
s[PCtlWtMchVCam, H];
s[Push, H];
ss[NxtStack, FromWrite];
Jmp[HandleMissPC];
};
};
= PStorePC => {
IF v[ASh] THEN {
Data is shared, generate WSRqst
First, read RCam to get the real address
ReadRCam1[SCmdLVM];
Jmp[PSRRCVM2PC];
};
IF NOT v[ASh] THEN {
Data is not shared, Every thing is automatic
Release processor
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
};
= PSRRCVM2PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 2
bus is quiet: go to next cycle
ReadRCam2[SCmdLVM];
Jmp[PSRRCVM3PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[PSRRCVM2PC];
};
};
= PSRRCVM3PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
Jmp[PSRRCVM4PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[PSRRCVM2PC];
};
};
= PSRRCVM4PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 4
bus is quiet: RCam is read
Rqst to arbiter, remember with NonFBTIP
s[PCtlSetNonFBTIP, H];
ReadRCam34[SCmdLVM];
Jmp[PSRCamReadyPC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[PSRRCVM2PC];
};
};
= PSRCamReadyPC => {
IF TRUE THEN {
Load Rqst buffer header with real address
s[PCtlLdRBufHeader, H];
ss[PCtlBCmd, BCmdWS];
ss[PCtlABusCmd, ABusCam];
Jmp[PSReturn2PC];
};
};
= PSReturn1PC => {
Blow one cycle to give NonFBTIP time to be set
IF TRUE THEN {
Jmp[PSReturn2PC];
};
};
= PSReturn2PC => {
IF v[NonFBTIP] AND NOT v[TimeOut] THEN {
Wait for WSRply, IOWRply, IORRply, BIOWRply, DeMapRply
s[PCtlSelRplyData, H];
Jmp[PSReturn2PC];
};
IF v[NonFBTIP] AND v[TimeOut] THEN {
timeOut : Signal and return
s[PCtlSelRplyData, H];
Jmp[StoreBTimeOutFaultPC];
};
IF NOT v[NonFBTIP] AND v[MyBFault] THEN {
WSRply has come back with a fault, release processor and return
s[PCtlFault, H];
s[PCtlSelBFC, H];
s[PCtlReleaseP, H];
s[PCtlSelRplyData, H];
Jmp[IdlePC];
};
IF NOT v[NonFBTIP] AND NOT v[MyBFault] THEN {
reply has come back, release processor and return
s[PCtlReleaseP, H];
s[PCtlSelRplyData, H];
Jmp[IdlePC];
};
};
= HandleMissPC => {
IF TRUE THEN {
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 the RBRply. Should be 2 cycles long. Cycle 1 of 2
s[PCtlFrzVictim, H];
Jmp[HM1PC];
};
};
= HM1PC => {
IF TRUE THEN {
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];
s[PCtlFrzVictim, H];
Jmp[HM2PC];
};
};
= HM2PC => {
IF v[RCamForP] THEN {
Wait Partial virtual match to complete, 3 of 3
continue the RCam read in case of match
Read RCam, cycle 2
ReadRCam2[SCmdLVM];
Jmp[HM3PPC];
};
IF NOT v[RCamForP] THEN {
Wait Partial virtual match to complete, 3 of 3
Read aborted by the bus side, redo it
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
Jmp[HM3nPPC];
};
};
= HM3PPC => {
IF v[AVM] AND v[RCamForP] THEN {
Partial virtual match is successful
bus is quiet, go to last cycle of Read RCam
Read RCam, cycle 3
ReadRCam34[SCmdLVM];
Jmp[HMRRCVM4PC];
};
IF v[AVM] AND NOT v[RCamForP] THEN {
Partial virtual match is successful
bus is busy: return to cycle 2
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
Jmp[HMRRCVM2PC];
};
IF NOT v[AVM] THEN {
Read AId from the Ram, first find it in the VCam
ss[PCtlABusCmd, ABusIOAId];
s[PCtlWtMchVCam, H];
Jmp[HMnMPC];
};
};
= HMnMPC => {
IF TRUE THEN {
Read AId from the Ram, cycle 1
Load output buffer with MapRqst|myId|PAdd
remember with NonFBTIP
s[PCtlLdRBufHeader, H];
ss[PCtlBCmd, BCmdMap];
ss[PCtlABusCmd, ABusPAdd];
ReadRam1[SCmdLVM];
Jmp[HMnM11PC];
};
};
= HMnM11PC => {
IF TRUE THEN {
Read AId from the Ram, cycle 2
Wait for AId to appear in the RRdLatch, 1 of 1
ReadRam2[SCmdLVM];
Jmp[HMnM12PC];
};
};
= HMnM12PC => {
IF v[RamForP] THEN {
Load lower data field with AId
Load upper data field with garbage
Request to the arbiter
s[PCtlSetNonFBTIP, H];
s[PCtlLdRBufDataLo, H];
s[PCtlLdRBufDataHi, H];
ReadRam3[SCmdLVM];
Jmp[HMnM3PC];
};
IF NOT v[RamForP] THEN {
Ratted! Just redo it
Read the Ram to get the AId value
ReadRam1[SCmdLVM];
Jmp[HMnM11PC];
};
};
= HMnM3PC => {
Blow one cycle to let NonFBTIP get set
IF TRUE THEN {
Jmp[HMnM4PC];
};
};
= HMnM4PC => {
IF v[NonFBTIP] AND NOT v[TimeOut] THEN {
Wait for MapRply to come back
s[PCtlFlagsForB, H];
Jmp[HMnM4PC];
};
IF v[NonFBTIP] AND v[TimeOut] THEN {
Time out : Signal and store the fault in the array
Jmp[StoreBTimeOutFaultPC];
};
IF NOT v[NonFBTIP] AND v[MyBFault] THEN {
MapCache fault: abort access
s[PCtlFault, H];
s[PCtlSelBFC, H];
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
IF NOT v[NonFBTIP] AND NOT v[MyBFault] THEN {
Load Rqst buffer header with read address
Read RCam using victim, cycle 1
Warning : Same as HMRCamReadyPC
s[PCtlLdRBufHeader, H];
ss[PCtlBCmd, BCmdRB];
ss[PCtlABusCmd, ABusCam];
ReadRCam1[SCmdVictim];
Jmp[HMRRCVct2PC];
};
};
= HM3nPPC => {
IF v[AVM] AND v[RCamForP] THEN {
Partial virtual match is successful
bus is quiet, go to next cycle (#3) of Read RCam
Read RCam, cycle 2
ReadRCam2[SCmdLVM];
Jmp[HMRRCVM3PC];
};
IF v[AVM] AND NOT v[RCamForP] THEN {
Partial virtual match is successful
bus is busy: return to cycle 2
Read RCam, cycle 1
ReadRCam1[SCmdLVM];
Jmp[HMRRCVM2PC];
};
IF NOT v[AVM] THEN {
Read AId from the Ram, first find it in the VCam
ss[PCtlABusCmd, ABusIOAId];
s[PCtlWtMchVCam, H];
Jmp[HMnMPC];
};
};
= HMRRCVM2PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 2
bus is quiet: go to next cycle
ReadRCam2[SCmdLVM];
Jmp[HMRRCVM3PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[HMRRCVM2PC];
};
};
= HMRRCVM3PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 3
bus is quiet: go to next cycle
ReadRCam34[SCmdLVM];
Jmp[HMRRCVM4PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[HMRRCVM2PC];
};
};
= HMRRCVM4PC => {
IF v[RCamForP] THEN {
Read RCam, cycle 4
bus is quiet: RCam is read
ReadRCam34[SCmdLVM];
Jmp[HMRCamReadyPC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdLVM];
Jmp[HMRRCVM2PC];
};
};
= HMRCamReadyPC => {
IF v[PAccessPermission] THEN {
Load Rqst buffer header with read address
Read RCam using victim, cycle 1
s[PCtlLdRBufHeader, H];
ss[PCtlBCmd, BCmdRB];
ss[PCtlABusCmd, ABusCam];
ReadRCam1[SCmdVictim];
Jmp[HMRRCVct2PC];
};
IF NOT v[PAccessPermission] THEN {
Fault : Signal and store in the array (can be done after having released the processor)
Jmp[StoreMemAccessFaultPC];
};
};
= HMRRCVct2PC => {
IF v[RCamForP] THEN {
Read RCam using victim, cycle 2
ReadRCam2[SCmdVictim];
Jmp[HMRRCVct3PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
Jmp[HMRRCVct2PC];
};
};
= HMRRCVct3PC => {
IF v[RCamForP] THEN {
Read RCam using victim, cycle 3
ReadRCam34[SCmdVictim];
Jmp[HMRRCVct4PC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
Jmp[HMRRCVct2PC];
};
};
= HMRRCVct4PC => {
IF v[RCamForP] THEN {
Read RCam using victim, cycle 4
ReadRCam34[SCmdVictim];
Jmp[HMReadRamPC];
};
IF NOT v[RCamForP] THEN {
Read RCam, cycle 1
bus is busy: return to cycle 2
ReadRCam1[SCmdVictim];
Jmp[HMRRCVct2PC];
};
};
= HMReadRamPC => {
IF TRUE THEN {
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];
ss[PCtlABusCmd, ABusRCam];
s[PCtlLdSnooper, H];
s[PCtlSetSnooperValid, H];
Jmp[HMRR2PC];
};
};
= HMRR2PC => {
IF TRUE THEN {
Wait for AOw. Read Ram, cycle 2
Load Buffer upper data field with garbage
ReadRam2[SCmdVictim, NoDBus];
ss[PCtlDBusCmd, DBusABus];
s[PCtlLdRBufDataLo, H];
s[PCtlLdRBufDataHi, H];
Jmp[HMRR3PC];
};
};
= HMRR3PC => {
IF v[RamForP] THEN {
Wait for AOw. Read Ram, cycle 3
ReadRam3[SCmdVictim, NoDBus];
Jmp[HMRR4PC];
};
IF NOT v[RamForP] THEN {
Redo the access including reloading the bridge between the ABus and the DBus
ReadRam1[SCmdVictim, NoDBus];
ss[PCtlABusCmd, ABusRCam];
Jmp[HMRR2PC];
};
};
= HMRR4PC => {
IF TRUE THEN {
Wait for AOw. Read Ram, cycle 4
Jmp[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.
= HMRR5PC => {
IF v[AOw] AND v[RPValid] THEN {
Generate FBRqst
ss[PCtlBCmd, BCmdFB];
ss[PCtlABusCmd, ABusRCam];
s[PCtlSetFBTIP, H];
s[PCtlLdFIFO, H];
Jmp[HMRR6PC];
};
IF NOT v[AOw] THEN {
Send RBRqst, remember with NonFBTIP
s[PCtlSetNonFBTIP, H];
Jmp[HMReturn1PC];
};
IF NOT v[RPValid] THEN {
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
s[PCtlSetNonFBTIP, H];
Jmp[HMReturn1PC];
};
};
= HMRR6PC => {
IF TRUE THEN {
Send RBRqst, remember with NonFBTIP
Put the address being read on the ABus to load the snooper when the FBRqst comes back
s[PCtlSetNonFBTIP, H];
ss[PCtlABusCmd, ABusRqstBuf];
Jmp[HMReturn1PC];
};
};
= HMReturn1PC => {
Blow one cycle to let NonFBTIP be set
IF TRUE THEN {
Jmp[HMReturn2PC];
}
};
= HMReturn2PC => {
IF v[NonFBTIP] AND NOT v[TimeOut] THEN {
Wait for rply to come back
Put the address being read on the ABus to load the snooper when the FBRqst comes back
ss[PCtlABusCmd, ABusRqstBuf];
s[PCtlSelRplyData, H];
Jmp[HMReturn2PC];
};
IF v[NonFBTIP] AND v[TimeOut] THEN {
TimeOut : Signal and store the fault in the array
s[PCtlSelRplyData, H];
Jmp[StoreBTimeOutFaultPC];
};
IF NOT v[NonFBTIP] AND v[MyBFault] THEN {
reply has come back with a fault, release processor and return
s[PCtlFault, H];
s[PCtlSelBFC, H];
s[PCtlReleaseP, H];
s[PCtlSelRplyData, H];
Jmp[IdlePC];
};
IF NOT v[NonFBTIP] AND NOT v[MyBFault] THEN {
s[PCtlShftVictim, H];
SELECT vs[Stack] FROM
=FromRead => {
Come from read: nothing else to do, just release the processor and the victim logic.
s[PCtlReleaseP, H];
s[PCtlSelRplyData, H];
Jmp[IdlePC];
};
= FromWrite => {
Try again, match VCam with Paddress
s[PCtlWtMchVCam, H];
Jmp[PSRetryPC];
};
= FromCWS => {
Try again, match VCam with Paddress
s[PCtlWtMchVCam, H];
Jmp[PCWSRetryPC];
};
ENDCASE => ERROR;
};
};
= StoreMemAccessFaultPC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultMemAccess];
Jmp[SMAF2PC];
};
};
= SMAF2PC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultMemAccess];
Jmp[SMAF3PC];
};
};
= SMAF3PC => {
IF v[RamForP] THEN {
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
s[PCtlFault, H];
ss[PCtlFaultCode, FaultMemAccess];
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
IF NOT v[RamForP] THEN {
Ratted! Redo the access
ss[PCtlDBusCmd, DBusABus];
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultMemAccess];
Jmp[SMAF2PC];
};
};
= StoreBTimeOutFaultPC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultBTimeOut];
Jmp[SBTOF2PC];
};
};
= SBTOF2PC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultBTimeOut];
Jmp[SBTOF3PC];
};
};
= SBTOF3PC => {
IF v[RamForP] THEN {
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
s[PCtlFault, H];
ss[PCtlFaultCode, FaultBTimeOut];
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
IF NOT v[RamForP] THEN {
Ratted! Redo the access
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultBTimeOut];
Jmp[SBTOF2PC];
};
};
= StoreIOAccessFaultPC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 1
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultIOAccess];
Jmp[SIOAF2PC];
};
};
= SIOAF2PC => {
IF TRUE THEN {
Write fault code into the RAM, cycle 2
WriteRam2[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultIOAccess];
Jmp[SIOAF3PC];
};
};
= SIOAF3PC => {
IF v[RamForP] THEN {
Write completed successfully. Go back to Idle loop
WriteRam3[SCmdLVM, DBusABus];
s[PCtlFault, H];
ss[PCtlFaultCode, FaultIOAccess];
s[PCtlReleaseP, H];
Jmp[IdlePC];
};
IF NOT v[RamForP] THEN {
Ratted! Redo the access
ss[PCtlDBusCmd, DBusABus];
WriteRam1[SCmdLVM, DBusABus];
ss[PCtlABusCmd, ABusFault+FaultIOAccess];
Jmp[SIOAF2PC];
};
};
ENDCASE => ERROR;
}
};
Internal Procs
Next: PROC [it: IndexType] RETURNS [index: NAT] = {
index ← Index[it];
Index[it] ← Index[it]+1;
};
Declare: PROC [name: ROPE, default: Level, st: SignalType] RETURNS [ix: NAT] = {
signals[numSignals] ← [name: name, st: st, default: default];
ix ← numSignals;
numSignals ← numSignals+1;
};
DeclareS: PROC [name: ROPE, size: NAT, defaultS: CARD, st: SignalType] RETURNS [ix: NAT] = {
signals[numSignals] ← [name: name, size: size, st: st, defaultS: defaultS];
ix ← numSignals;
numSignals ← numSignals+1;
};
XInLS: PROC [ls: LevelSequence] RETURNS [BOOLFALSE] = {
FOR i: NAT IN [0..ls.size) DO IF ls[i]=X THEN RETURN [TRUE] ENDLOOP;
};
pmCodeName: ROPE = Rosemary.Register[roseClassName: "PmCode", init: Init, evalSimple: Simple];
RosemaryUser.RegisterTestProc["Test", Test];
END.