FSM.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Barth, July 17, 1987 5:42:41 pm PDT
Last Edited by: Don Curry December 12, 1987 12:04:48 pm PST
DIRECTORY Core, CoreClasses, IO, Sisyph, SymTab;
FSM: CEDAR DEFINITIONS = BEGIN
Theory
This interface defines some routines for creating finite state machines and their corresponding cellTypes from either code or schematics. The cellTypes can be created with or without a register for the outputs. When a cellType without a register is created, all outputs have the prefix 'Nxt' to distinguish the signal names from inputs which where outputs from the previous cycle. The cellTypes have a high level Rosemary eval proc and will recast into a variety of cell types depending on the parameter exprImplKey. See FSMImpl.mesa for the latest catalogue of implementation choices for exprImplKey.
Public Types - (for direct contruction of FSMData)
FSMData:   TYPE = REF FSMDataRec;
FSMDataRec:  TYPE = RECORD [
name:    IO.ROPE    ← NIL,
states:    States     ← NIL,
initialState:  State     ← NIL,
register:   RegisterType   ← edgeTriggered,
mach:    Expression   ← NIL, -- private
assert:    Expression   ← NIL, -- any guaranteed conditions
publics:   LIST OF IO.ROPE  ← NIL, -- private
srcCellType:  Core.CellType  ← NIL ]; -- private
States:  TYPE = LIST OF State;
State:  TYPE = REF StateRec;
StateRec: TYPE = RECORD [
name:   IO.ROPE    ← NIL,
outputs:  LIST OF IO.ROPE  ← NIL, -- Moore state and outs, Mealy state
outputsInv: LIST OF IO.ROPE  ← NIL,  -- explicit control of state encodings
outTrans:  Transitions   ← NIL,
inTrans:  Transitions   ← NIL, -- private
srcCellInst: CellInstance   ← NIL ]; -- private
Transitions: TYPE = LIST OF Transition;
Transition: TYPE = REF TransitionRec;
TransitionRec: TYPE = RECORD [
enable:  Expression   ← NIL,
outputs:  LIST OF IO.ROPE  ← NIL,  -- Mealy outs
target:   State     ← NIL,
srcCellInst: CellInstance   ← NIL ]; -- private
Expression:  TYPE = REF;
CellInstance:  TYPE = CoreClasses.CellInstance;
RegisterType: TYPE = {edgeTriggered, twoPhase, none};
Private Types - (used during indirect contruction of FSMData)
Context:  TYPE = REF ContextRec;
ContextRec: TYPE = RECORD[
fsm:   FSMData,
logic:   LIST OF CurrentLogic,
data:   LIST OF CurrentData,
state:   IO.ROPE,
declares:  LIST OF Declaration, -- Used during declarations
signals:  Signals,     -- Used after all declarations
invTab:  SymTab.Ref,
stateTab:  SymTab.Ref ];
CurrentLogic: TYPE = LIST OF FieldValMask ← NIL;
CurrentData:  TYPE = LIST OF FieldValMask ← NIL;
FieldValMask: TYPE = RECORD[f,v,m: NAT ← default];
Signals:   TYPE = REF SignalSeqRec;
SignalSeqRec: TYPE = RECORD [SEQUENCE size: NAT OF Declaration];
Declaration:  TYPE = RECORD [name: IO.ROPE, io: InOut, size: NAT, index: NAT];
InOut:   TYPE = {in, out};
default:   NAT = LAST[NAT];
Creation of FSM CellTypes from FSMData or Schematics
CodeMachine: PROC [fsm: FSMData, exprImplKey: ATOM ← $SC] RETURNS [ct: Core.CellType];
fsm.publics, fsm.mach and all inTrans fields are initialized to NIL.
SchStateCell:   PROC RETURNS [ct: Core.CellType]; -- Target Source
SchTransitionCell: PROC RETURNS [ct: Core.CellType]; -- Source Target
SchMachine: PROC [
cx:    Sisyph.Context,
name:   IO.ROPE  ← NIL,
register:  RegisterType ← edgeTriggered,
exprImplKey: ATOM   ← $SC    ]
RETURNS [ct: Core.CellType];
Sch cell name: ".fsm" is concatenated to name if supplied or the current object name if not.
Sisyph is invoked to extract the schematic state machine.
A state labelled Init must exist.
Every state has an implicit transition to Init when Reset is asserted.
The names used in the public of the cellType will be:
"Vdd", "Gnd", "Reset",
all input names,
all output names (including automatically assigned xtra state bit names),
SELECT registerType FROM
edgeTriggered => "Clock"
twoPhase    => "PhA", "PhB"
ENDCASE   => 'Nxt' prepended to all outputs which are also inputs,
Generating FSMData
The following procs are useful for writing FSM Generators.
You create a context: ctx ← Create[]
Declare names:   id: NAT ← ctx.Declare[name, in/out, size]
Specify the function: ctx.IfState["state1"]; ctx.AddOut[id, val]; ctx.JmpState["state2"]; ...
And finish:    fsm ← ctx.Finish[]
IfReset, IfState, and If push the context down one level.
JmpState, and EndIf pop the context up one level.
Only IfReset and IfState can be used at the top level.
Only If can be used at lower levels.
And is used to extend a condition started by IfState or If.
IfReset provides an efficient means to define an initial state which is reached from any state when the signal with the reserved name "Reset" is asserted. Since "Reset" is assumed to be unconditional, only output specificaton calls (AddOut) should come between the IfReset call and its terminating JmpState call.
Create: PROC[name: IO.ROPE] RETURNS[ctx: Context];
Declare: PROC[ctx: Context, name: IO.ROPE, io: InOut, size: NAT ← 1] RETURNS[ix: NAT];
IfReset:  PROC[ctx: Context];
IfState:  PROC[ctx: Context, s: IO.ROPE];
If:    PROC[ctx: Context, f, v: NAT, m: NAT ← default];
And:   PROC[ctx: Context, f, v: NAT, m: NAT ← default];
AddOut:  PROC[ctx: Context, f, v: NAT, m: NAT ← default];
JmpState: PROC[ctx: Context, s: IO.ROPE];
EndIf:  PROC[ctx: Context];
Finish:  PROC[ctx: Context] RETURNS[mach: FSMData];
Complete state assignments and convert to an Expression
EncodeStates: PROC[fsm: FSMData];           -- multiple calls ok
ConvertToExp: PROC[fsm: FSMData] RETURNS[machine: LIST OF REF]; -- calls EncodeStates
Build Standard Cells
ImplementExprFile: PROC[file: IO.ROPE, register: RegisterType, exprImplKey: ATOM]
RETURNS[Core.CellType];
ImplementExpr: PROC[mach: Expression, register: RegisterType, exprImplKey: ATOM]
RETURNS[Core.CellType];
BuildSCMachine: PROC[mach: Expression] RETURNS [Core.CellType];
BuildSCGates:  PROC[mach: Expression] RETURNS [Core.CellType];
BuildSCRegister: PROC[mach: Expression] RETURNS [Core.CellType];
END.