ArbiterImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Gasbarro April 3, 1987 9:44:13 am PST
DIRECTORY
Arbiter, BitOps, Core, CoreClasses, CoreCreate, CoreProperties, FIFOQueue, DynaBusInterface, Ports, Rosemary, RosemaryUser;
ArbiterImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreCreate, FIFOQueue, Ports, Rosemary
EXPORTS Arbiter
= BEGIN
DReq, Reset, Clock, DGrant, Vdd, Gnd: NATLAST[NAT];
ROPE: TYPE = Core.ROPE;
Port: TYPE = Ports.Port;
Cmd: TYPE = DynaBusInterface.Cmd;
reqBits: CARDINAL = 2;
reqIdle: CARDINAL = 3;
seize: CARDINAL = 2;
reqTwo: CARDINAL = 1;
reqFive: CARDINAL = 0;
Reply2: ATOM = $Reply2;
Reply5: ATOM = $Reply5;
maxRequestsPend: CARDINAL ← 3;
requestsPend: CARDINAL ← 0;
grantCycles: CARDINAL ← 0;
grantDelay: CARDINAL ← 0;
busLocked: BOOLFALSE;
queue: FIFOQueue.Queue ← NIL;
currentReq: ATOMNIL;
prevClock: BOOLFALSE;
Create: PUBLIC PROC RETURNS [ct: Core.CellType] = {
ct ← CoreClasses.CreateUnspecified[
public: CoreCreate.WireList[LIST[CoreCreate.Seq["DReq", reqBits], "Reset", "Clock", "DGrant", "Vdd", "Gnd"], "Arbiter", NIL],
name: arbiterName
];
[] ← Rosemary.BindCellType[cellType: ct, roseClassName: arbiterName];
InitPortIndicies[ct];
[] ← Ports.InitPorts[ct, b, force, "DGrant"];
[] ← Ports.InitPorts[ct, b, none, "Reset", "Clock"];
[] ← Ports.InitPorts[ct, c, none, "DReq"];
};
Init: Rosemary.InitProc = {
--PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [stateAny: REF ANY ← NIL]--
queue ← FIFOQueue.Create[];
};
Simple: Rosemary.EvalProc = {
--PROC [p: Ports.Port, stateAny: REF ANY]--
IF prevClock=p[Clock].b THEN RETURN; --edge sensitive
prevClock ← p[Clock].b;
IF NOT p[Clock].b THEN RETURN; --filter falling edge
IF p[Reset].b THEN {
requestsPend ← 0;
grantCycles ← 0;
grantDelay ← 0;
busLocked ← FALSE;
queue ← FIFOQueue.Create[];
currentReq ← NIL;
prevClock ← FALSE;
};
SELECT p[DReq].c FROM
reqIdle => busLocked ← FALSE;
reqTwo => {
FIFOQueue.Include[queue, Reply2];
requestsPend ← requestsPend+1;
IF requestsPend > maxRequestsPend THEN ERROR;
};
reqFive => {
FIFOQueue.Include[queue, Reply5];
requestsPend ← requestsPend+1;
IF requestsPend > maxRequestsPend THEN ERROR;
};
seize => busLocked ← TRUE;
ENDCASE => ERROR;
IF currentReq=NIL AND NOT FIFOQueue.IsEmpty[queue] THEN {
currentReq ← NARROW[FIFOQueue.Remove[queue]];
grantCycles ← IF currentReq=Reply2 THEN 2 ELSE 5;
grantDelay ← 5; --a very simple arbiter delay model
};
IF currentReq#NIL AND grantDelay=0 THEN {
IF grantCycles#0 THEN {
p[DGrant].b ← TRUE ;
grantCycles ← grantCycles-1;
} ELSE {
p[DGrant].b ← FALSE;
currentReq ← NIL;
requestsPend ← requestsPend-1;
};
};
IF grantDelay#0 THEN grantDelay ← grantDelay-1;
};
InitPortIndicies: PROC [ct: Core.CellType] = {
[DReq, Reset, Clock, DGrant, Vdd, Gnd] ← Ports.PortIndexes[ct.public, "DReq", "Reset", "Clock", "DGrant", "Vdd", "Gnd"];
};
BusIsLocked: PUBLIC PROC RETURNS [BOOL] = {
RETURN[busLocked];
};
arbiterName: ROPE = Rosemary.Register[roseClassName: "Arbiter", init: Init, evalSimple: Simple];
END.