PBusEmulImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Created by Jean Gastinel, April 21, 1988 11:05:27 am PDT
Pradeep Sindhu May 4, 1988 0:28:50 am PDT
Jean Gastinel June 7, 1988 6:34:14 pm PDT
DIRECTORY
Atom, PBusConex, PBusEmul, Ports, Rope;
PBusEmulImpl: CEDAR PROGRAM
IMPORTS Atom, Ports
EXPORTS PBusEmul
~ BEGIN
Service Types
PBusEvent: SIGNAL [msg: Rope.ROPE]= CODE;
QWord: TYPE = ARRAY [0 .. 2) OF CARD;
WordAsBits: TYPE = PACKED ARRAY [0..16) OF BOOL;
DWAsBits: TYPE = PACKED ARRAY [0..32) OF BOOL;
SimpleProc: TYPE = PROC[pbusemul: PBusConex.PBusEmulState, params: LIST OF REF ANYNIL ] RETURNS [];
HARDWARE DEFINITIONS
Definition of the PCmd format
PCmdRead: NAT= 8;
PCmdWrite: NAT= 9;
PCmdIORead: NAT= 12;
PCmdIOWrite: NAT= 13;
PCmdBIOWrite: NAT= 15;
PCmdCWS: NAT= 10;
PCmdDeMap: NAT= 11;
PCmdClearVP: NAT= 14;
Service Procs
StopSimul: SimpleProc ~ {
SIGNAL PBusEvent["End of Simulation"];
NextLine[pbusemul];
};
NextLine: SimpleProc ~ {
pbusemul.testProcList ← pbusemul.testProcList.rest;
pbusemul.cycleCount ← 0;
};
Jump: SimpleProc ~ {
Jump to cycle line number : lnb
label: ATOMNARROW[params.first];
pbusemul.testProcList ← NARROW[Atom.GetProp[$PBusEmul, $PKList]];
WHILE pbusemul.testProcList.first # label DO
NextLine[pbusemul];
ENDLOOP;
Emul[pbusemul];
};
B: PROC [b: BOOL] RETURNS [rb: REF ANY] = {rb ← NEW[BOOL ← b]};
Interprocess Synchronisation
WaitSync: SimpleProc ~ {
This proc is use for synchronisation. It tests the value of a parameter atom $Flag.
During the wait, a nop command is generated
Flag: ATOMNARROW[params.first];
Cond: BOOL;
IF Atom.GetProp[$Sync,Flag]=NIL THEN Cond ← FALSE
ELSE Cond ← NARROW[Atom.GetProp[$Sync,Flag],REF BOOL]^;
IF Cond THEN IF pbusemul.numClockEdges MOD 4 = 3 THEN NextLine[pbusemul];
};
SkipIfTrue: SimpleProc ~ {
This proc is used for synchronisation. It tests the value of the parameter atom $Flag.
If the parameter is True, the next instruction is skiped. If it is Not True the
following instructions are normally executed.
Flag: ATOMNARROW[params.first];
Cond: BOOL;
IF Atom.GetProp[$Sync,Flag]=NIL THEN Cond ← FALSE
ELSE Cond ← NARROW[Atom.GetProp[$Sync,Flag],REF BOOL]^;
NextLine[pbusemul];
IF Cond THEN NextLine[pbusemul];
Emul[pbusemul] ;
};
SetFlag: SimpleProc ~ {
This proc is use for synchronisation. It Set the value of a parameter atom $Flag
to TRUE
Flag: ATOMNARROW[params.first];
Atom.PutProp[$Sync,Flag, B[TRUE]];
NextLine[pbusemul];
Emul[pbusemul]
};
ClearFlag: SimpleProc ~ {
This proc is use for synchronisation. It Clears the value of a parameter atom $Flag
to FALSE
Flag: ATOMNARROW[params.first];
Atom.PutProp[$Sync,Flag, B[FALSE]];
NextLine[pbusemul];
Emul[pbusemul]
};
Wait: SimpleProc ~ {
This proc advances cycleCount to pbusCycles (pbusCycle=4*dynabusCycle)
pbusCycles: CARDNARROW[params.first, REF CARD]^;
IF pbusemul.cycleCount < pbusCycles*4 THEN pbusemul.cycleCount ← pbusemul.cycleCount+1
ELSE NextLine[pbusemul];
};
SetMode: SimpleProc ~ {
This proc set the Mode output at "Kernel" if the parameter =0, at User if not.
Mode: CARDNARROW[params.first, REF CARD]^;
IF Mode=0 THEN pbusemul.PMode ← L ELSE pbusemul.PMode ← H;
NextLine[pbusemul];
Emul[pbusemul]
};
SetByteSelect: SimpleProc ~ {
This proc set the ByteSelect output with the value of the parameter.
ByteSelect: CARDNARROW[params.first, REF CARD]^;
Ports.LCToLS[ByteSelect,pbusemul.PByteSel];   -- 0FH =Word selection
NextLine[pbusemul];
Emul[pbusemul]
};
CheckPFault: PROC [pbusemul: PBusConex.PBusEmulState , faultCheck : CARD] RETURNS [] ~ {
This proc Check the value of the Fault Bus.
faultCode : CARD;
faultCode ← 0;
IF pbusemul.PFault = H THEN {
faultCode ← 16 + Ports.LSToLC[pbusemul.PFaultCode];
IF faultCode ~= faultCheck THEN SIGNAL PBusEvent["Error PFault Code"];
pbusemul.PFaultChecked ← TRUE;
};
};
ReadAndCheck: SimpleProc ~ {
This proc send a read command. The first parameter is the Address,
the second, the expected data.
address, data, dataread, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdRead,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => pbusemul.cycleCount← pbusemul.cycleCount+1;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
ENABLE Ports.ConversionError => {SIGNAL PBusEvent["X in input"]; NextLine[pbusemul]; GOTO Done};
dataread ← Ports.LSToLC[pbusemul.PDataIn];
IF (data~=dataread) THEN SIGNAL PBusEvent["Error Read Compare Data"];
IF faultCheck ~= 0 THEN IF pbusemul.PFaultChecked = FALSE THEN SIGNAL PBusEvent["No PFault occurs"];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
EXITS
Done => NULL
};
Write: SimpleProc ~ {
This proc send a Write command. The first parameter is the Address,
the second is the Data sent.
address, data, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;

Ports.LCToLS[PCmdWrite,pbusemul.PCmd];  -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];  -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => {
Ports.LCToLS[data,pbusemul.PDataOut];
pbusemul.cycleCount← pbusemul.cycleCount+1};
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
Ports.LCToLS[data,pbusemul.PDataOut];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
};
IOReadAndCheck: SimpleProc ~ {
This proc send a IORead command. The first parameter is the Address,
the second, the expected data.
data, dataread, address, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdIORead,pbusemul.PCmd];  -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];  -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => pbusemul.cycleCount← pbusemul.cycleCount+1;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
ENABLE Ports.ConversionError => {SIGNAL PBusEvent["X in input"]; NextLine[pbusemul]; GOTO Done};
dataread ← Ports.LSToLC[pbusemul.PDataIn];
IF (data~=dataread) THEN SIGNAL PBusEvent["Error Read Compare Data"];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
EXITS
Done => NULL
};
IOWrite: SimpleProc ~ {
This proc send a IOWrite command.The first parameter is the Address,
the second is the Data sent.
data , address, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdIOWrite,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => {
Ports.LCToLS[data,pbusemul.PDataOut];
pbusemul.cycleCount← pbusemul.cycleCount+1} ;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
Ports.LCToLS[data,pbusemul.PDataOut];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
};
BIOWrite: SimpleProc ~ {
This proc send a BIOWrite command.The first parameter is the Address,
the second is the Data sent.
data , address, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdBIOWrite,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => {
Ports.LCToLS[data,pbusemul.PDataOut];
pbusemul.cycleCount← pbusemul.cycleCount+1} ;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
Ports.LCToLS[data,pbusemul.PDataOut];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
};


PBusCmd: SimpleProc ~ {
This proc generate any command on the PCBus
};
CondWriteSingleAndCheck: SimpleProc ~ {
This proc send a read command. The first parameter is the Address,
the second, the expected data.
address, data, dataread, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
data ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdCWS,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => pbusemul.cycleCount← pbusemul.cycleCount+1;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
ENABLE Ports.ConversionError => {SIGNAL PBusEvent["X in input"]; NextLine[pbusemul]; GOTO Done};
dataread ← Ports.LSToLC[pbusemul.PDataIn];
IF (data~=dataread) THEN SIGNAL PBusEvent["Error Read Compare Data"];
IF faultCheck ~= 0 THEN IF pbusemul.PFaultChecked = FALSE THEN SIGNAL PBusEvent["No PFault occurs"];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
EXITS
Done => NULL
};
DeMap: SimpleProc ~ {
This proc send a DeMap command. The first parameter is the Address.
address, faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
address ← NARROW[par1.first, REF CARD]^; par1 ← par1.rest;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdDeMap,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[address,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => pbusemul.cycleCount← pbusemul.cycleCount+1;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
Ports.LCToLS[0,pbusemul.PDataOut];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
};
ClearVP: SimpleProc ~ {
This proc send a ClearVP command. No parameter.
faultCheck : CARD;
par1 : LIST OF REF ANY ← params;
IF par1 = NIL THEN faultCheck 𡤀 ELSE faultCheck ← NARROW[par1.first, REF CARD]^;
Ports.LCToLS[PCmdClearVP,pbusemul.PCmd];   -- Command
SELECT pbusemul.cycleCount FROM
0,1 => {
Ports.LCToLS[0,pbusemul.PDataOut];   -- Send Address
pbusemul.cycleCount← pbusemul.cycleCount+1 };
2 => pbusemul.cycleCount← pbusemul.cycleCount+1;
3 => {
CheckPFault[pbusemul,faultCheck];
IF pbusemul.PReject=L
THEN {
Ports.LCToLS[0,pbusemul.PDataOut];
NextLine[pbusemul] }
ELSE pbusemul.cycleCount 𡤀
};
ENDCASE => ERROR;
};
A: PROC [c: CARD] RETURNS [rc: REF ANY] = {rc ← NEW[CARD ← c]};
Simulation Procs
Interpretation Motor
AtomDidSomething: PROC [pbusemul: PBusConex.PBusEmulState, atom: ATOM, params: LIST OF REF ANY] RETURNS [BOOL] =
{
v: REF ANY = Atom.GetProp[$PBusEmul, atom];
IF v # NIL THEN {
spr: REF SimpleProc = NARROW[v];
spr^[pbusemul, params];
RETURN[TRUE];
}
ELSE {
NextLine[pbusemul];
RETURN[FALSE];
};
};
Emul: PUBLIC PROC [pbusemul: PBusConex.PBusEmulState] ~ {
IF pbusemul.testProcList = NIL THEN {
pbusemul.testProcList ← NARROW[Atom.GetProp[$PBusEmul, $PKList]];
};
DO
WITH pbusemul.testProcList.first SELECT FROM
atom: ATOM => IF AtomDidSomething[pbusemul, atom, NIL] THEN EXIT;
list: LIST OF REF ANY => {
WITH list.first SELECT FROM
atom: ATOM => IF AtomDidSomething[pbusemul, atom, list.rest] THEN EXIT;
ENDCASE => ERROR;
};
ENDCASE => ERROR;
ENDLOOP;
};
Atom.PutProp[$PBusEmul, $StopSimul, NEW[SimpleProc ← StopSimul]];
Atom.PutProp[$PBusEmul, $Wait, NEW[SimpleProc ← Wait]];
Atom.PutProp[$PBusEmul, $Jump, NEW[SimpleProc ← Jump]];
Atom.PutProp[$PBusEmul, $WaitSync, NEW[SimpleProc ← WaitSync]];
Atom.PutProp[$PBusEmul, $SetFlag, NEW[SimpleProc ← SetFlag]];
Atom.PutProp[$PBusEmul, $ClearFlag, NEW[SimpleProc ← ClearFlag]];
Atom.PutProp[$PBusEmul, $SkipIfTrue, NEW[SimpleProc ← SkipIfTrue]];
Atom.PutProp[$PBusEmul, $ReadAndCheck, NEW[SimpleProc ← ReadAndCheck]];
Atom.PutProp[$PBusEmul, $Write, NEW[SimpleProc ← Write]];
Atom.PutProp[$PBusEmul, $IOReadAndCheck, NEW[SimpleProc ← IOReadAndCheck]];
Atom.PutProp[$PBusEmul, $IOWrite, NEW[SimpleProc ← IOWrite]];
Atom.PutProp[$PBusEmul, $BIOWrite, NEW[SimpleProc ← BIOWrite]];
Atom.PutProp[$PBusEmul, $PBusCmd, NEW[SimpleProc ← PBusCmd]];
Atom.PutProp[$PBusEmul, $CondWriteSingleAndCheck, NEW[SimpleProc ← CondWriteSingleAndCheck]];
Atom.PutProp[$PBusEmul, $DeMap, NEW[SimpleProc ← DeMap]];
Atom.PutProp[$PBusEmul, $ClearVP, NEW[SimpleProc ← ClearVP]];
Atom.PutProp[$PBusEmul, $SetMode, NEW[SimpleProc ← SetMode]];
Atom.PutProp[$PBusEmul, $SetByteSelect, NEW[SimpleProc ← SetByteSelect]];
Atom.PutProp[$PBusEmul, $PKList, LIST[
$Nop,
LIST[$Jump, $Nop]
]];
END.