PCEmulImpl.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Created by Jean Gastinel, May 27, 1988 11:29:31 am PDT
DIRECTORY
Atom, Basics, PCConex, PCEmul, Ports, Rope;
PCEmulImpl: CEDAR PROGRAM
IMPORTS Atom, Basics, Ports
EXPORTS PCEmul
~ BEGIN
Service Types
Mismatch: SIGNAL [msg: Rope.ROPE]= CODE;
PCEvent: 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[pcemul: PCConex.PCEmulState, params: LIST OF REF ANYNIL ] RETURNS [];
HARDWARE DEFINITIONS
Definition of the DbugBus register
DSerialOut: NAT= 8;
nDReset: NAT= 10;
nDFreeze: NAT= 11;
DExecute: NAT= 12;
DSerialIn: NAT= 13;
DAddress: NAT= 14;
DShiftCk: NAT= 15;
Address of the DbugBus Register on the PC Bus
dRegister: NAT=600FH;
Service Procs
DynaBus Synchronisation
StopSimul: SimpleProc ~ {
SIGNAL PCEvent["End of Simulation"];
NextLine[pcemul];
};
NextLine: SimpleProc ~ {
pcemul.testProcList ← pcemul.testProcList.rest;
pcemul.countcycle ← 0;
};
Jump: SimpleProc ~ {
Jump to cycle line number : lnb
label: ATOMNARROW[params.first];
pcemul.testProcList ← NARROW[Atom.GetProp[$PCEmul, $PKList]];
WHILE pcemul.testProcList.first # label DO
NextLine[pcemul];
ENDLOOP;
};
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
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 NextLine[pcemul];
};
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[pcemul];
};
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[pcemul];
};
Wait: SimpleProc ~ {
This proc count "countcycle" cycle before going to the next instruction
countcycle: CARDNARROW[params.first, REF CARD]^;
IF pcemul.countcycle < countcycle THEN pcemul.countcycle ← pcemul.countcycle + 1
ELSE NextLine[pcemul];
};
Init: SimpleProc~ {
This proc inits the DbugBus register with Reset active
pcemul.dataout[nDReset] ← L;
pcemul.dataout[nDFreeze] ← H;
pcemul.dataout[DExecute] ← L;
pcemul.dataout[DSerialIn] ← L;
pcemul.dataout[DAddress] ← L;
pcemul.dataout[DShiftCk] ← L;
pcemul.nIORPC ← H;
Ports.CToLS[dRegister,pcemul.address];
SELECT pcemul.countcycle FROM
0 => {
pcemul.nIOWPC ← L;
pcemul.countcycle← pcemul.countcycle+1}
ENDCASE => {
pcemul.nIOWPC ← H;
NextLine[pcemul]}
};
Reset: SimpleProc~ {
This proc activates Reset for 10 cycles
IF pcemul.nIOWPC=H
THEN {
pcemul.nIOWPC← L;
SELECT pcemul.countcycle FROM
0 => {
pcemul.dataout[nDReset] ← L;
pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1};
IN [1..6] => {
pcemul.dataout[DShiftCk] ← L;
pcemul.countcycle← pcemul.countcycle+1};
7=> {
pcemul.dataout[nDReset] ← H;
pcemul.countcycle← pcemul.countcycle+1};
ENDCASE => {
pcemul.dataout[DShiftCk] ← L;
NextLine[pcemul]};
}
ELSE pcemul.nIOWPC← H;
};
ResetOn: SimpleProc~ {
This proc put Reset On
IF pcemul.nIOWPC=H
THEN {
pcemul.nIOWPC← L;
SELECT pcemul.countcycle FROM
0 => {
pcemul.dataout[nDReset] ← L;
pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1};
1 => {
pcemul.dataout[DShiftCk] ← L;
pcemul.countcycle← pcemul.countcycle+1};
ENDCASE => {
pcemul.dataout[DShiftCk] ← L;
NextLine[pcemul]};
}
ELSE pcemul.nIOWPC← H;
};
ResetOff: SimpleProc~ {
This proc put Reset Off
IF pcemul.nIOWPC=H
THEN {
pcemul.nIOWPC← L;
SELECT pcemul.countcycle FROM
0 => {
pcemul.dataout[nDReset] ← H;
pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1};
1 => {
pcemul.dataout[DShiftCk] ← L;
pcemul.countcycle← pcemul.countcycle+1};
ENDCASE => {
pcemul.dataout[DShiftCk] ← L;
NextLine[pcemul]};
}
ELSE pcemul.nIOWPC← H;
};
SendDBusAddress: SimpleProc ~ {
This proc send an address to the DBugBus
adrs: CARDINALNARROW[params.first, REF CARDINAL]^;
adrsbits: WordAsBits ← LOOPHOLE[adrs];
IF pcemul.nIOWPC=H
THEN {
pcemul.nIOWPC← L;
SELECT pcemul.countcycle FROM
IN [0..32) => {
pcemul.dataout[DAddress] ← H;
IF (pcemul.countcycle MOD 2)=0
THEN {
pcemul.dataout[DShiftCk] ← L;
pcemul.dataout[DSerialIn] ← IF adrsbits[pcemul.countcycle/2] THEN H ELSE L}
ELSE pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1;
};
ENDCASE => {
pcemul.countcycle← pcemul.countcycle+1;
pcemul.dataout[DAddress] ← L;
pcemul.dataout[DShiftCk] ← L};
}
ELSE IF pcemul.countcycle < 33 THEN pcemul.nIOWPC← H
ELSE { pcemul.nIOWPC← H;
NextLine[pcemul]};
};
SendDBusData: SimpleProc ~ {
This proc send an address to the DBugBus
nb: CARDINALNARROW[params.rest.first, REF CARDINAL]^; --number of bits to send
data: CARDNARROW[params.first, REF CARD]^;
databits: DWAsBits← LOOPHOLE[Basics.SwapHalves[LOOPHOLE[data]]];
IF pcemul.nIOWPC=H
THEN {
pcemul.nIOWPC← L;
IF pcemul.countcycle < 2*nb
THEN {
IF (pcemul.countcycle MOD 2)=0
THEN {
pcemul.dataout[DShiftCk] ← L;
pcemul.dataout[DSerialIn] ← IF databits[32-nb+pcemul.countcycle/2] THEN H ELSE L}
ELSE pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1}
ELSE {
pcemul.countcycle← pcemul.countcycle+1;
pcemul.dataout[DShiftCk] ← L;
};
}
ELSE IF pcemul.countcycle < 2*nb+1 THEN pcemul.nIOWPC← H
ELSE { pcemul.nIOWPC← H;
NextLine[pcemul]};
};
ReadDBusAndCheck: SimpleProc ~ {
This proc read a data from the DbugBus and compare with a value
nb: CARDINALNARROW[params.rest.first, REF CARDINAL]^; --number of bits to read
value: CARDNARROW[params.first, REF CARD]^;
valuebits: DWAsBits← LOOPHOLE[Basics.SwapHalves[LOOPHOLE[value]]];
IF pcemul.nIOWPC=H AND pcemul.nIORPC=H
THEN {
pcemul.nIOWPC← L;
pcemul.nIORPC ← H;
IF pcemul.countcycle < 2*nb
THEN {
IF (pcemul.countcycle MOD 2)=0
THEN pcemul.dataout[DShiftCk] ← L
ELSE pcemul.dataout[DShiftCk] ← H;
pcemul.countcycle← pcemul.countcycle+1}
ELSE {
pcemul.countcycle← pcemul.countcycle+1;
pcemul.dataout[DShiftCk] ← L;
};
}
ELSE {
IF pcemul.countcycle < 2*nb+1
THEN {
pcemul.nIOWPC← H;
IF (pcemul.countcycle MOD 2)=1 THEN
IF pcemul.nIORPC=H
THEN pcemul.nIORPC ← L
ELSE {
IF pcemul.datain[DSerialOut] ~= (IF valuebits[32-nb+pcemul.countcycle/2] THEN H ELSE L) THEN SIGNAL Mismatch["Error compare data"];
pcemul.nIORPC ← H};
}
ELSE { pcemul.nIOWPC← H;
pcemul.nIORPC ← H;
NextLine[pcemul];}
};
};
A: PROC [c: CARD] RETURNS [rc: REF ANY] = {rc ← NEW[CARD ← c]};
Q: PROC [c: QWord] RETURNS [rc: REF ANY] = {rc ← NEW[QWord ← c]};
Simulation Procs
Interpretation Motor
Emul: PUBLIC PROC [pcemul: PCConex.PCEmulState] RETURNS [] ~ {
IF pcemul.testProcList = NIL THEN {
pcemul.testProcList ← NARROW[Atom.GetProp[$PCEmul, $PKList]];
};
DO
AtomDidSomething: PROC [atom: ATOM, params: LIST OF REF ANY] RETURNS [BOOL] =
{
v: REF ANY = Atom.GetProp[$PCEmul, atom];
IF v # NIL THEN {
spr: REF SimpleProc = NARROW[v];
spr^[pcemul, params];
RETURN[TRUE];
}
ELSE {
NextLine[pcemul];
RETURN[FALSE];
};
};
WITH pcemul.testProcList.first SELECT FROM
atom: ATOM => IF AtomDidSomething[atom, NIL] THEN EXIT;
list: LIST OF REF ANY => {
WITH list.first SELECT FROM
atom: ATOM => IF AtomDidSomething[atom, list.rest] THEN EXIT;
ENDCASE => ERROR;
};
ENDCASE => ERROR;
ENDLOOP;
};
Atom.PutProp[$PCEmul, $Wait, NEW[SimpleProc ← Wait]];
Atom.PutProp[$PCEmul, $Jump, NEW[SimpleProc ← Jump]];
Atom.PutProp[$PCEmul, $Init, NEW[SimpleProc ← Init]];
Atom.PutProp[$PCEmul, $Reset, NEW[SimpleProc ← Reset]];
Atom.PutProp[$PCEmul, $ResetOn, NEW[SimpleProc ← ResetOn]];
Atom.PutProp[$PCEmul, $ResetOff, NEW[SimpleProc ← ResetOff]];
Atom.PutProp[$PCEmul, $StopSimul, NEW[SimpleProc ← StopSimul]];
Atom.PutProp[$PCEmul, $WaitSync, NEW[SimpleProc ← WaitSync]];
Atom.PutProp[$PCEmul, $SetFlag, NEW[SimpleProc ← SetFlag]];
Atom.PutProp[$PCEmul, $ClearFlag, NEW[SimpleProc ← ClearFlag]];
Atom.PutProp[$PCEmul, $SendDBusAddress, NEW[SimpleProc ← SendDBusAddress]];
Atom.PutProp[$PCEmul, $SendDBusData, NEW[SimpleProc ← SendDBusData]];
Atom.PutProp[$PCEmul, $ReadDBusAndCheck, NEW[SimpleProc ← ReadDBusAndCheck]];
Atom.PutProp[$PCEmul, $PKList, LIST[
$Nop,
LIST[$Jump, $Nop]
]];
END.