[Indigo]<Rosemary>2.6>Rosemary.DF=>RoseClocksImpl.Mesa
Last Edited by: Spreitzer, January 23, 1985 5:46:33 pm PST
Last Edited by: Barth, June 9, 1983 11:09 am
DIRECTORY
Cucumber, NumTypes, IO, PrincOps, PrincOpsUtils, Process, Rope, RoseClocks, RoseCreate, RoseEvents, RoseRun, RoseTypes, 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:
ROPE ←
IO.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,
expandProc: NIL,
ioCreator: CreateClockGenIO,
initializer: InitializeClockGen,
evals: [EvalSimple: ClockGenSimple],
ports: clockGenPorts,
typeData: NEW [RoseClockArgs ← args] ];
};
ClockGenIORef: TYPE = REF ClockGenIORec;
ClockGenIORec:
TYPE =
MACHINE
DEPENDENT
RECORD [
fill1(0:0..14): [0..32767],
phi1(0:15..15): BOOLEAN,
fill2(1:0..14): [0..32767],
phi2(1:15..15): BOOLEAN];
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]
RETURNS [ioAsAny:
REF
ANY]
--RoseTypes.IOCreator-- =
BEGIN
ioAsAny ← NEW [ClockGenIORec];
END;
InitializeClockGen: RoseTypes.Initializer =
BEGIN
cgi: ClockType ← NARROW[cell.type.typeData];
newIO: ClockGenIORef ← NARROW[cell.realCellStuff.newIO];
oldIO: ClockGenIORef ← NARROW[cell.realCellStuff.oldIO];
[newIO.phi1, newIO.phi2] ← StateToBits[cgi.sense][Initial[cgi.style]];
IF leafily
THEN
TRUSTED BEGIN
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] ]];
cell.realCellStuff.state ← cs;
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;
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: RoseTypes.CellProc
--PROC [cell: Cell]-- = {
cs: ClockState ← NARROW[cell.realCellStuff.state];
newIO: ClockGenIORef ← NARROW[cell.realCellStuff.newIO];
[newIO.phi1, newIO.phi2] ← StateToBits[cs.type.sense][cs.display.state];
};
clockGenPorts: RoseTypes.Ports ← NEW [RoseTypes.PortsRep[2]];
Setup:
PROC =
BEGIN
clockGenPorts[0] ← [firstWord: 0, wordCount: 1, name: "PhaseA", type: NumTypes.boolType, output: TRUE];
clockGenPorts[1] ← [firstWord: 1, wordCount: 1, name: "PhaseB", type: NumTypes.boolType, output: TRUE];
clockHandler.Register[CODE[ClockStateRep]];
displayHandler.Register[CODE[DisplayRep]];
END;
Setup[];
END.