NewRosemaryRPC.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Barth, June 9, 1988 5:55:09 pm PDT
DIRECTORY BitOps, Core, CoreClasses, CoreFlat, RefTab, Rope;
NewRosemaryRPC: CEDAR DEFINITIONS = BEGIN
Theory
This interface contains the division between that which happens on a local machine and that which happens on a remote machine. Until a simulation is instantiated nothing resides on the remote machine. When the simulation is instantiated:
The Core is transferred to the remote machine.
The behavioural procedures are bound with the server side of the simulator.
The server side is run on the remote machine.
The simulation data structure is created on the remote machine.
ROPE: TYPE = Rope.ROPE;
Stop: SIGNAL [msg: ROPENIL, data: REF ANYNIL, reason: ATOM ← $Client];
This signal may be raised when a behavioural proc is annoyed by something. It is raised by Rosemary with reason = $BoolWireHasX and data = CoreFlat.FlatWire if some wire attached to a port containing boolean values settles to an X.
Behaviour Registration
BindCellType: PROC [cellType: Core.CellType, roseClassName: ROPE] RETURNS [sameCellType: Core.CellType];
BindCellClass: PROC [cellClass: Core.CellClass, roseClassName: ROPE] RETURNS [sameCellClass: Core.CellClass];
Register: PROC [roseClassName: ROPE, init: InitProc ← NIL, evalSimple: EvalProc ← NIL, scheduleIfClockEval: BOOLFALSE] RETURNS [sameRoseClassName: ROPE];
InitProc: TYPE = PROC [cellType: Core.CellType, flatCellType: CoreFlat.FlatCellType, oldStateAny: REF ANYNIL] RETURNS [stateAny: REF ANYNIL, stateValue: LevelSequence ← NIL];
Initializes the state and the value from the context contained in the cell type. Multiple calls must return different copies of any bits in the state record which actually represent the state of the simulation. If oldStateAny is not NIL then the procedure should reset the state to its initial value rather than allocating new state. stateValue contains a representation of the state value. It is not required. The InitProc and EvalProc own stateValue, Rosemary guarantees not to change it. The size of stateValue, when specified, must be constant across calls to InitProc and EvalProc.
EvalProc: TYPE = PROC [stateAny: REF ANY, clockEval: BOOL] RETURNS [stateValue: LevelSequence ← NIL];
Must be idempotent. clockEval indicates that only ports combinatorially derived from a clock should be changed, i.e. no state should be updated during such an evaluation. stateValue is the same as in InitProc.
Instantiation
All of the procedures in this section which take Core.Wire arguments may only be called with atomic, canonical (in the CoreFlat sense) wires.
SetFixedWire: PROC [wire: Core.Wire, level: Level ← L] RETURNS [sameWire: Core.Wire];
Sets the value of the wire and indicates that the value of the wire may not be changed by Rosemary. This is only intended to be used for atomic public wires of the root cell type such as Vdd and Gnd. These wires partition the network into disjoint blocks connected through transistor gates. It is not a general purpose mechanism for jamming a value onto a wire.
SetWireSize: PROC [wire: Core.Wire, size: WireSize ← charge] RETURNS [sameWire: Core.Wire];
WireSize: TYPE = Drive[chargeWeak..chargeStrong];
SetWireLevel: PROC [wire: Core.Wire, level: Level ← X] RETURNS [sameWire: Core.Wire];
SetWireMemory: PROC [wire: Core.Wire, memory: BOOLFALSE] RETURNS [sameWire: Core.Wire];
If memory is false then the wire is set to X whenever the wire is not driven and the memory boolean in the Settle call is false.
SetTransistorCellTypeSize: PROC [transistor: Core.CellType, size: TransistorSize] RETURNS [sameTransistor: Core.CellType];
Sets the order of magnitude transistor size.
SetTransistorInstanceSize: PROC [transistor: CoreClasses.CellInstance, size: TransistorSize] RETURNS [sameTransistor: CoreClasses.CellInstance];
TransistorSize: TYPE = Drive[driveWeak..driveStrong];
Instantiate: PROC [cellType: Core.CellType, cutSet: CoreFlat.CutSet ← NIL] RETURNS [simulation: RoseSimulation];
Flattens the given cell type using the cutSet to determine the leaves of the simulation.
Relaxation
Initialize: PROC [simulation: RoseSimulation, updateCellProc: UpdateCellProc ← NIL];
Reset the state. The InitProc for each behaviour class is called for each instance. The UpdateCellProc is called after each init (c.f. Settle).
Settle: PROC [simulation: RoseSimulation, memory: BOOLTRUE, clockEval: BOOLFALSE, updateWireProc: UpdateWireProc ← NIL, updateCellProc: UpdateCellProc ← NIL];
UpdateWireProc: TYPE = PROC [roseWire: RoseWire];
UpdateCellProc: TYPE = PROC [roseInstance: RoseCellInstance, stateValue: LevelSequence];
Relaxes the simulation. If an update procedure is supplied it is called each time a RoseWire changes value. May raise Stop. If memory is false then all wires which do not have memory are set to X if they are not driven. clockEval is passed to all of the eval procs so that they may take appropriate action and is used to empty the deferred eval queue.
State Access
NotInstantiated: SIGNAL;
Raised when access is requested to data not contained in the current simulation.
GetWireValue: PROC [simulation: RoseSimulation, flatWire: CoreFlat.FlatWire] RETURNS [value: LevelSequence];
Gets the current value of the wire. May raise NotInstantiated.
GetStateRef: PROC [simulation: RoseSimulation, flatCell: CoreFlat.FlatCellType] RETURNS [stateAny: REF ANY];
Returns the ref to flatCell's state. Raises NotInstantiated if flatCell was not a leaf during instantiation.
Ports
Creation
CreatePorts: PROC [simulation: RoseSimulation, flatWire: CoreFlat.FlatWire] RETURNS [ports: RosePorts];
Creates an ordered set of ports which correspond to the atomic wires of flatWire and hooks them into the simulation.
BindPort: PROC [simulation: RoseSimulation, cell: Core.CellType, flatCell: CoreFlat.FlatCellType, name: Rope.ROPE] RETURNS [p: RosePorts];
Same as CreatePorts but uses name as a full wire name in the public of cell to create the flatWire passed to CreatePorts.
BindPorts: PROC [simulation: RoseSimulation, cell: Core.CellType, flatCell: CoreFlat.FlatCellType, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11: Rope.ROPENIL] RETURNS [p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11: RosePorts ← NIL];
Same as BindPort but for a pile of them.
Drive
GetDrive, GD: PROC [p: RosePorts] RETURNS [v: Drive];
Dies if p is not an atomic port and all the drives are not the same.
PutDrive, PD: PROC [p: RosePorts, v: Drive];
GetDriveSequence, GDS: PROC [p: RosePorts, i: NAT] RETURNS [v: Drive];
PutDriveSequence, PDS: PROC [p: RosePorts, i: NAT, v: Drive];
Value
GetLevel, GL: PROC [p: RosePorts] RETURNS [v: Level];
PutLevel, PL: PROC [p: RosePorts, v: Level, d: Drive ← drive];
GetLevelSequence, GLS: PROC [p: RosePorts, i: NAT] RETURNS [v: Level];
PutLevelSequence, PLS: PROC [p: RosePorts, i: NAT, v: Level, d: Drive ← drive];
GetBool, GB: PROC [p: RosePorts] RETURNS [v: BOOL];
PutBool, PB: PROC [p: RosePorts, v: BOOL, d: Drive ← drive];
GetBoolSequence, GBS: PROC [p: RosePorts, i: NAT] RETURNS [v: BOOL];
PutBoolSequence, PBS: PROC [p: RosePorts, i: NAT, v: BOOL, d: Drive ← drive];
GetWord, GW: PROC [p: RosePorts] RETURNS [v: BitOps.BitWord];
PutWord, PW: PROC [p: RosePorts, v: BitOps.BitWord, d: Drive ← drive];
GetDWord, GDW: PROC [p: RosePorts] RETURNS [v: BitOps.BitDWord];
PutDWord, PDW: PROC [p: RosePorts, v: BitOps.BitDWord, d: Drive ← drive];
GetQWord, GQW: PROC [p: RosePorts] RETURNS [v: BitOps.BitQWord];
PutQWord, PQW: PROC [p: RosePorts, v: BitOps.BitQWord, d: Drive ← drive];
Utilities
Not: PROC [src, dst: RosePorts];
Copy: PROC [src, dst: RosePorts];
Set: PROC [p: RosePorts, v: Level];
AnyX: PROC [p: RosePorts] RETURNS [BOOL];
ToRope: PROC [p: RosePorts, size: NAT ← 0, base: NAT ← 16] RETURNS [r: Rope.ROPE];
size is the number of high order bits in p to be converted. 0 => all of them
Size: PROC [p: RosePorts] RETURNS [size: NAT];
Data Structures
Level: TYPE = {L, H, X};
LevelSequence: TYPE = REF LevelSequenceRec;
LevelSequenceRec: TYPE = RECORD [
s: PACKED SEQUENCE size: NAT OF Level];
Drive: TYPE = {
inspect, -- allows test port to receive value
expect, -- allows test port to specify expected value
none, --in a test port it means neither driven nor checked; in an eval port it means no strength at all
chargeWeak, chargeMediumWeak,
charge,
chargeMediumStrong, chargeStrong,
force, -- weakest drive level, allows test procs to check if device has tristated
driveWeak, driveMediumWeak,
drive,
driveMediumStrong, driveStrong,
infinite -- drive for nodes which have infinite current sources
};
DriveSequence: TYPE = REF DriveSequenceRec;
DriveSequenceRec: TYPE = RECORD [
s: PACKED SEQUENCE size: NAT OF Drive];
RoseSimulation: TYPE = REF RoseSimulationRec;
RoseSimulationRec: PUBLIC TYPE = RECORD [
cellType: Core.CellType ← NIL,
coreToRoseWires: RefTab.Ref ← NIL,
coreToRoseInstances: RefTab.Ref ← NIL,
instanceNeedEval: RoseCellInstance ← NIL,
instanceNeedEvalWhenNotClockEval: RoseCellInstance ← NIL,
perturbed: RoseWire ← NIL,
vicinityByStrength: ARRAY Drive OF VicinityRec,
time: INT ← 0];
VicinityRec: TYPE = RECORD[
wires: RoseWires,
firstFree: CARDINAL ← 0];
RoseCellType: TYPE = REF RoseCellTypeRec;
RoseCellTypeRec: TYPE = RECORD [
init: InitProc ← NIL,
evalSimple: EvalProc ← NIL,
scheduleIfClockEval: BOOLFALSE];
RoseCellInstances: TYPE = LIST OF RoseCellInstance;
RoseCellInstance: TYPE = REF RoseCellInstanceRec;
RoseCellInstanceRec: TYPE = RECORD [
nextNeedEval: RoseCellInstance ← NIL,
nextNeedEvalWhenNotClockEval: RoseCellInstance ← NIL,
roseCellType: RoseCellType ← NIL,
state: REF ANYNIL,
log: RoseLog ← NIL,
flatCellType: CoreFlat.FlatCellTypeRec];
RoseWireList: TYPE = LIST OF RoseWire;
RoseWires: TYPE = REF RoseWireSeq;
RoseWireSeq: TYPE = RECORD [s: SEQUENCE size: CARDINAL OF RoseWire];
RoseWire: TYPE = REF RoseWireRec;
RoseWireRec: TYPE = RECORD [
ports: RosePorts ← NIL,
nextPerturbedWire: RoseWire ← NIL,
previousPerturbedWire: RoseWire ← NIL,
nextRecomputed: RoseWire ← NIL,
nextVicinityWire: RoseWire ← NIL,
channels: RoseTransistors ← NIL,
notOffChannels: RoseTransistors ← NIL,
validNotOffChannels: CARDINAL ← 0,
gates: RoseTransistors ← NIL,
switchDrive: Drive ← none,
upDrive: Drive ← none,
downDrive: Drive ← none,
wireDrive: Drive ← charge,
wireValue: Level ← L,
mark: BOOLFALSE,
memory: BOOLFALSE,
log: RoseLog ← NIL,
flatWire: CoreFlat.FlatWireRec];
RoseTransistors: TYPE = REF RoseTransistorSeq;
RoseTransistorSeq: TYPE = RECORD [s: SEQUENCE size: CARDINAL OF RoseTransistor];
RoseTransistor: TYPE = REF RoseTransistorRec;
RoseTransistorRec: TYPE = RECORD [
gate: RoseWire ← NIL,
ch1: RoseWire ← NIL,
ch2: RoseWire ← NIL,
conductivity: Drive ← drive,
transistorType: CoreClasses.TransistorType ← nE,
flatCellType: CoreFlat.FlatCellTypeRec];
RosePorts: TYPE = REF RosePortSeq;
RosePortSeq: TYPE = RECORD [s: SEQUENCE size: CARDINAL OF RosePort];
RosePort: TYPE = REF RosePortRec;
RosePortRec: TYPE = RECORD [
instance: RoseCellInstance ← NIL,
level: Level ← X,
drive: Drive ← none,
wire: RoseWire ← NIL];
The plan is to write all the data for all of the wires and cells on the remote disk. All of the data for each wire or cell that is currently plotted is also stored in the VM of the local machine. The remote machine knows which wires are currently plotted and calls the local machine with any updates.
RoseLog: TYPE = REF RoseLogRec;
RoseLogRec: TYPE = RECORD [
lastFilePos: INT ← -1, -- the file position of the last sample written
list: RoseSampleList ← NIL, -- if non-nil, the samples for this object are currently kept in memory
previous: RoseSample ← NIL, -- the previous sample
currentTime: INT ← -1, -- time of current sample
current: RoseSample ← NIL]; -- the sample currently taken, not guaranteed if time=lastUpdateTime ???? what is time and lastUpdateTime RB
The following assertions must hold:
- current.next = NIL
- current.time = value of time at last call to Update
- current will never be modified once time of Update call > current.time
- previous is the sample that was valid just before current. It is necessary to allow collapsing current with a previous value. previous has not yet been written to disk!
- if previous#NIL, then previous.next=current
- if list#NIL, then samples are kept in memory. Then, either list.head=previous=NIL, or previous may be reached by following next links from list.head (possibly 0 times!).
RoseSampleList: TYPE = REF RoseSampleListRec;
RoseSampleListRec: TYPE ~ RECORD [
head: RoseSample, -- the head of the list. The tail is always LogData.current
beforeHeadPos: INT, -- the file position of the predecessor of head, <0 => no predecessor
inTable: BOOLFALSE]; -- used internally to RBT management, don't modify
The in-memory representation of a list of samples. The samples back in time may still be on disk, starting at beforeHeadPos. SampleLists are created only when necessary.
RoseSample: TYPE = REF RoseSampleRec;
RoseSampleRec: TYPE = RECORD [
next: RoseSample ← NIL,
time: INTLAST[INT], -- time at which this event occured
value: PACKED SEQUENCE size: CARDINAL OF Level];
The object has the specified value in the range [sample.time..sample.next.time)
END.