[Indigo]<Rosemary>®>Rosemary.DF=>RoseClocksImpl.Mesa
Last Edited by: Spreitzer, May 1, 1985 11:37:26 pm PDT
Last Edited by: Barth, June 9, 1983 11:09 am
DIRECTORY Basics, BitTwiddling, Cucumber, NumTypes, IO, PrincOps, PrincOpsUtils, Process, Rope, RoseClocks, RoseCreate, RoseEvents, RoseRun, RoseTypes, SwitchTypes, ViewRec;
RoseClocksImpl: CEDAR MONITOR
IMPORTS Cucumber, IO, NumTypes, PrincOpsUtils, Process, RoseCreate, RoseEvents, RoseRun, RoseTypes, VR: ViewRec
EXPORTS RoseClocks =
BEGIN OPEN RoseClocks;
ROPE: TYPE = Rope.ROPE;
Cell: TYPE = RoseTypes.Cell;
ClockType: TYPE = REF RoseClockArgs;
ClockGen: PUBLIC PROC [args: RoseClockArgs] RETURNS [ct: RoseTypes.CellType] =
{name: ROPEIO.PutFR[
"ClockGen[%g,%g]",
IO.rope[SELECT args.sense FROM ActiveHigh => "ActiveHigh", ActiveLow => "ActiveLow", ENDCASE => ERROR],
IO.rope[SELECT args.style FROM TwoStep => "TwoStep", FourStep => "FourStep", ENDCASE => ERROR]];
IF (ct ← RoseCreate.GetCellType[name]) # NIL THEN RETURN;
ct ← RoseCreate.RegisterCellType[
name: name,
ioCreator: CreateClockGenIO,
driveCreator: CreateClockGenDrive,
initializer: InitializeClockGen,
evals: [EvalSimple: ClockGenSimple],
ports: clockGenPorts,
typeData: NEW [RoseClockArgs ← args] ];
};
ClockGenSimpleIORef: TYPE = REF ClockGenSimpleIORec;
ClockGenSimpleIORec: TYPE = RECORD [
phil: [0 .. BitTwiddling.TwoToThe[Basics.bitsPerWord-2]) ← 0,
phi1, phi2: BOOL];
ClockGenSwitchIORef: TYPE = REF ClockGenSwitchIORec;
ClockGenSwitchIORec: TYPE = RECORD [
phi1, phi2: SwitchTypes.SwitchVal];
ClockGenDriveRef: TYPE = REF ClockGenDriveRec;
ClockGenDriveRec: TYPE = RECORD [
tag: RoseTypes.DriveTagType,
drives: PACKED ARRAY ClockGenPort OF RoseTypes.DriveLevel];
ClockGenPort: TYPE = {phi1, phi2, fill2, fill3};
ClockState: TYPE = REF ClockStateRep;
ClockStateRep: TYPE = RECORD [
type: ClockType,
display: Display,
rv: VR.RecordViewer,
cell, root: Cell,
notice: CONDITION,
stopResponse: StopResponse ← Abort,
stopped: PrincOps.FrameHandle ← NIL];
StopResponse: TYPE = {Resume, Abort};
Display: TYPE = REF DisplayRep;
DisplayRep: TYPE = RECORD [
sofar: INTEGER,
state: State,
status: Status ← Normal,
Cycle: PROC [cell: Cell, cycles: CARDINAL],
Step: PROC [cell: Cell],
Interrupt: PROC,
Disable: PROC [cell: Cell] RETURNS [ok: BOOL],
Proceed, Abort: PROC [cell: Cell] ];
State: TYPE = [0..6);
Status: TYPE = {Normal, Interrupted};
clockHandler: Cucumber.Handler ← NEW [Cucumber.HandlerRep ← [
PrepareWhole: PrepareClock,
PartTransfer: TransferClock]];
displayHandler: Cucumber.Handler ← NEW [Cucumber.HandlerRep ← [
PartTransfer: TransferDisplay]];
PrepareClock: Cucumber.Bracket--PROC [whole: REF ANY, where: IO.STREAM, direction: Direction, data: REF ANY] RETURNS [leaveTheseToMe: SelectorList ← NIL]-- =
{leaveTheseToMe ← LIST[$notice]};
TransferClock: Cucumber.PartTransferProc = UNCHECKED
BEGIN
cs: ClockState ← NARROW[whole];
SELECT part.first FROM
$type, $rv, $cell, $root, $notice, $stopped => NULL;
$display => Cucumber.Transfer[what: cs.display, where: where, direction: direction];
ENDCASE => ERROR Cucumber.Error[IO.PutFR["Unexpected field %g in Clock State", IO.atom[NARROW[part.first]]]];
END;
TransferDisplay: Cucumber.PartTransferProc = {};
CreateClockGenIO: PROC [ct: RoseTypes.CellType, switch: BOOL] RETURNS [ioAsAny: REF ANY] --RoseTypes.IOCreator-- =
{ioAsAny ← IF switch THEN NEW [ClockGenSwitchIORec] ELSE NEW [ClockGenSimpleIORec]};
CreateClockGenDrive: PROC [ct: RoseTypes.CellType] RETURNS [driveAsAny: REF ANY] --RoseTypes.DriveCreator-- =
{driveAsAny ← NEW [ClockGenDriveRec]};
InitializeClockGen: RoseTypes.Initializer =
BEGIN
cgi: ClockType ← NARROW[cell.type.typeData];
newIO: ClockGenSimpleIORef ← NARROW[cell.realCellStuff.newIO];
oldIO: ClockGenSimpleIORef ← NARROW[cell.realCellStuff.oldIO];
display: Display ← NEW [DisplayRep ← [
sofar: 0,
state: Initial[cgi.style],
Cycle: DoCycle,
Step: DoStep,
Interrupt: Interrupt,
Disable: Disable,
Proceed: Proceed,
Abort: Abort ]];
cs: ClockState ← NEW [ClockStateRep ← [
type: cgi,
display: display,
cell: cell,
root: RootCell[cell] ]];
[newIO.phi1, newIO.phi2] ← StateToBits[cgi.sense][Initial[cgi.style]];
cell.realCellStuff.state ← cs;
TRUSTED {Process.InitializeCondition[condition: @cs.notice, ticks: Process.SecondsToTicks[5]]};
cs.rv ← VR.ViewRef[
agg: display,
specs: CONS[["state", Value[val: NIL, visible: TRUE, dontAssign: TRUE]],
CONS[["sofar", Value[val: NIL, visible: TRUE, dontAssign: TRUE]],
CONS[["status", Value[val: NIL, visible: TRUE, dontAssign: TRUE]],
VR.BindAllOfATypeFromRefs[rec: display, handle: NEW [Cell ← cell]] ]]],
viewerInit: [name: cell.name, iconic: FALSE],
createOptions: [exclusiveProcs: FALSE]];
END;
RootCell: PROC [cell: Cell] RETURNS [root: Cell] =
{FOR root ← cell, root.parent WHILE root.parent # NIL DO NULL ENDLOOP};
Initial: ARRAY Style OF State = [5, 0];
Interrupt: PROC = {RoseRun.stop ← TRUE};
Disable: PROC [cell: Cell] RETURNS [ok: BOOL] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
ok ← (cs.stopped # NIL) AND RoseRun.DisableThisStop[cs.stopped];
END;
Proceed: ENTRY PROC [cell: Cell] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
cs.stopResponse ← Resume;
cs.display.status ← Normal;
BROADCAST cs.notice;
END;
Abort: ENTRY PROC [cell: Cell] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
cs.stopResponse ← Abort;
cs.display.status ← Normal;
BROADCAST cs.notice;
END;
GetStopResponse: ENTRY PROC [cell: Cell, msg: ROPE, data: REF ANY] RETURNS [sr: StopResponse] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
RoseEvents.Notify[$Interrupt, NIL, TRUE];
TRUSTED {cs.stopped ← PrincOpsUtils.MyLocalFrame[]};
cs.display.status ← Interrupted;
cs.rv.DisplayMessage[msg];
WHILE cs.display.status = Interrupted DO
WAIT cs.notice;
ENDLOOP;
RoseRun.stop ← FALSE;
sr ← cs.stopResponse;
cs.stopped ← NIL;
RoseEvents.Notify[$Start, NIL, TRUE];
END;
DoStep: PROC [cell: Cell] =
BEGIN
RoseEvents.Notify[$Start, NIL, TRUE];
Step[cell !UNWIND => RoseEvents.Notify[$Stop, NIL, TRUE]];
RoseEvents.Notify[$Stop, NIL, TRUE];
END;
Step: PUBLIC PROC [cell: Cell] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
cs.display.state ← Transitions[cs.display.state];
RoseRun.ScheduleCell[cell];
RoseRun.Run[cell.sim
!RoseTypes.Stop => CHECKED
BEGIN
SELECT GetStopResponse[cell, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END];
END;
DoCycle: PROC [cell: Cell, cycles: CARDINAL] =
BEGIN
RoseEvents.Notify[$Start, NIL, TRUE];
Cycle[cell, cycles !UNWIND => RoseEvents.Notify[$Stop, NIL, TRUE]];
RoseEvents.Notify[$Stop, NIL, TRUE];
END;
Cycle: PUBLIC PROC [cell: Cell, cycles: CARDINAL] =
BEGIN
cs: ClockState ← NARROW[cell.realCellStuff.state];
cs.display.sofar ← 0;
DO
IF cs.display.state = TestTime[cs.type.style] THEN
BEGIN
IF cycles < 1 THEN EXIT;
cycles ← cycles - 1;
cs.display.sofar ← cs.display.sofar + 1;
END;
Step[cell];
IF cs.display.state = EndTime[cs.type.style] THEN RoseEvents.Notify[$EndOfClockCycle, cs.root, TRUE
!RoseTypes.Stop => CHECKED
BEGIN
SELECT GetStopResponse[cell, msg, data] FROM
Resume => RESUME;
Abort => ERROR ABORTED;
ENDCASE => ERROR;
END];
ENDLOOP;
END;
TestTime: ARRAY Style OF State = [5, 0];
EndTime: ARRAY Style OF State = [5, 3];
Transitions: ARRAY State OF State = [1, 2, 3, 0, 5, 4];
StateToBits: ARRAY Sense OF ARRAY State OF RECORD [BOOL, BOOL] =
[
[
[FALSE, FALSE],
[TRUE, FALSE],
[FALSE, FALSE],
[FALSE, TRUE],
[TRUE, FALSE],
[FALSE, TRUE] ],
[
[TRUE, TRUE],
[FALSE, TRUE],
[TRUE, TRUE],
[TRUE, FALSE],
[FALSE, TRUE],
[TRUE, FALSE] ] ];
ClockGenSimple: PROC [cell: Cell, perturb: PROC [portIndex: RoseTypes.PortIndex]] --RoseTypes.CellProc-- = {
cs: ClockState ← NARROW[cell.realCellStuff.state];
newIO: ClockGenSimpleIORef ← NARROW[cell.realCellStuff.newIO];
[newIO.phi1, newIO.phi2] ← StateToBits[cs.type.sense][cs.display.state];
};
clockGenPorts: RoseTypes.Ports ← NEW [RoseTypes.PortsRep[2]];
bpw: NAT = Basics.bitsPerWord;
bps: NAT = SwitchTypes.bitsPerSwitchVal;
Setup: PROC =
BEGIN
clockGenPorts[0] ← [
simple: [0, bpw-2, 1],
switch: [0, 0, bps],
name: "PhaseA",
type: NumTypes.boolType,
output: TRUE];
clockGenPorts[1] ← [
simple: [0, bpw-1, 1],
switch: [1, 0, bps],
name: "PhaseB",
type: NumTypes.boolType,
output: TRUE];
clockHandler.Register[CODE[ClockStateRep]];
displayHandler.Register[CODE[DisplayRep]];
END;
Setup[];
END.