SAKURA, A BRIEF DESCRIPTION
Nori Suzuki and Rod Burstall July 81

Filed on: SakuraDescription.txt Last edit: July 14, 1981 11:51 AM

This is a short description of Sakura to enable other people to experiment with the language and provide us with feedback. Sakura is a language for specifying the behaviour of hardware devices. It is based on Mesa, but has facilities for concurrency which we hope will be easier to use for hardware description than the Mesa facilities. Our intention is to implement Sakura as a Mesa front end, i.e. to write a tranlator into Mesa. Mesa will be available as a sublanguage (perhaps with some restrictions, yet to be defined), and the translator will simply pass out most of the Mesa text untouched. The concurrency is handled by a scheduler which makes random choices about what to run next but in a reasonably fair way so that the apparent time taken by each operation is not widely variable; thus delaying one process allows the others to "settle down".

We can define
devices which have some code, internal state and input and output to communicate with other devices. To make a network of devices we define some connectors and say how they connect the devices together. We can also give a circuit of a device as a network of other devices. We may attach a guardian to a device which intercepts its input signals and checks that they conform to some conditions.
Because the language is an extension of mesa we will use the Mesa syntax class names from the Mesa Manual and indicate new syntax classes peculiar to Sakura by underlining them. We will us S, . . . , S to mean a (possibly empty) sequence of S’s separated by commas (similarly for other separators).

Device declarations

A device is defined with a heading similar to a Mesa procedure declaration, an Input list, an Output list, a Guardian and a body with three parts State, Dataflow and Control. The Guardian gives conditions for acceptable input, the State gives the local variables which are affected by concurrent processes, the Dataflow serves to instantly update values of dependent variables and the Control corresponds to the usual idea of procedure body, giving the "code" for the device. These will be described in more detail below. The device body can include a
circuit consisting of a whole network of devices (see the section on circuits below).

DeviceDeclaration ::= Identifier: DEVICE[ParameterList] =
{
IN Idlist: TypeSpecification, . . . ,Idlist: TypeSpecification
OUT Idlist: TypeSpecification, . . . ,Idlist: TypeSpecification
GUARDIAN Block
DeviceBody}

DeviceBody
::=
STATE DeclarationSeries
DATAFLOW Transfer; . . . ; Transfer
CONTROL Block

Example:

-- FIRST IN FIRST OUT BUFFER DEFINITION

Fifo: DEVICE [Init, WriteRequest, ReadRequest: BOOLEAN,
DataIn:CARDINAL]
RETURNS [SpaceAv, DataAv: BOOLEAN,
DataOut: CARDINAL] =
{
GUARDIAN
{Initialized: BOOLEAN := FALSE;
DO PAR {
WHEN Init UP
IF ReadRequest OR WriteRequest THEN ERROR;
Initialized := TRUE ||
WHEN ReadRequest UP
IF NOT Initialized OR Init OR NOT DataAv THEN ERROR ||
WHEN WriteRequest UP
IF NOT Initialized OR Init OR NOT SpaceAv THEN ERROR }
ENDLOOP }
STATE A: ARRAY[1..37] of CARDINAL; rp, wp: BOOLEAN
DATAFLOW
DataAv <= NOT ReadRequest AND rp<wp,
SpaceAv <= NOT WriteRequest AND wp<wp+size,
A[wp] <= DataIn,
DataOut <= A[rp]
CONTROL
DO
WHEN Init UP rp := wp := 0;
QUITON Init UP IN
PAR {DO WHEN ReadRequest UP : rp := rp+1 ENDLOOP
//
DO WHEN WriteRequest UP : wp := wp+1 ENDLOOP }
ENDLOOP
} -- end of FIFO DEFINITION

Guardians

A guardian enforces some restrictions on the input to a device. The device is not intended to simulate the hardware being tested unless the input data satisfies these restrictions. The other devices should not provide it with such illegal data, and the guardian provides a run time check on this (it may be swithched off for efficiency. The guardian may declare local variables to "remember" properties of the previous input sequence and it may (?) access the state variables of the device which it guards. The code for a guardian is a statement, i.e. a Mesa statement extended with some additional Sakura constructions (see below).


Dataflow


The dataflow part of a device is intended to simulate the instantaneous behavior of some hardware. It consists of a sequence of transfers, each analogous to an assignment, with a left and right side. As soon as the value of any variable on the left hand side is changed the values of all the dependent variables on the right hand side are recomputed, and this recomputation is iterated until these values stabilise.

Transfer ::= Variable <= Expression |
Variable[Expression] <= Expression
Example:
DataAv <= NOT ReadRequest AND rp<wp

Control

The control gives the body of the procedure. It consists of a Sakura statement which is a Mesa statement permitting several extra syntactic constructions.

Statement ::=
PAR { Statement // . . . // Statement}|
Guarded command [] . . . [] Guarded command|
WHEN Event : Statement|
ON Event Statement IN Statement|
(other kinds of statement as in Mesa)

Guarded command ::=WHEN Event Statement

Event ::=UpDownSignal|
UpDownSignal AND Expression

UpDownSignal ::=Identifier UP | Identifier DOWN

A
parallel statement using PAR simply executes its substatements concurrently using the Mesa fork and join mechanism. When one of the branches refers to an input (i.e. argument), output (i.e. result) or state variable of the device control is passed to the Sakura scheduler which may elect with some randomness to run other concurrent statements and resume the present one later.

A
guarded command consists of an event and a statement which is to be executed if the event occurs. A statement consisting of a set of guarded commands is executed by seeing which event occurs first and then executing the statement of the corresponding guarded command.

An
event is associated with a Boolean identifier and occurs when that identifier changes its value from true to false (UP) or vice versa (DOWN); if however the event is qualified by a Boolean expression this must evaluate to true for the event to occur.

A
WHEN statement consists of an event and a substatement. Execution is held up (and control passed to the Sakura scheduler) until that event occurs, at which point the statement is executed. (????######)

An
ON statement, ON E S1 IN S2, executes statement S2 but if at any time during its execution event E occurs, execution of S2 is terminated and S1 is executed. Of course such changes of control can only occur when the scheduler is given control because reference is made to an input, output or state variable.

Circuits

A block in Sakura may also consist of a
circuit. This is a network of devices connected together. The connections are made by using newly introduced nodes or inputs or outputs of the parent device. When the block is executed the circuit starts running.

Block
::= Circuit |
(other kinds of block as in Mesa)

Circuit ::= CIRCUIT {
COMPONENTS Idlist: Call, . . ., Idlist: Call
NODES: Idlist: TypeSpecification, . . . ,
Idlist: TypeSpecification
REPRESENTATION Alias, . . . , Alias
CONNECTIONS Connection, . . . , Connection
}
Alias::= Variable, . . . , Variable ALIAS Variable ##??##

Connection ::= Identifier( Keyword: Identifier, . . ., Keyword: Identifier)
The components part consists of a sequence of idedifier lists followed by a call, which is the application of a device to some arguments. The nodes used in the circuit are each given a type, such as Boolean or Cardinal, corresponding to the type of value they transmit. The connection statements each consist of a device identifier and a sequence of node identifiers each associated with a keyword to show which input or output of the device it is to be attached to.

Example:

CIRCUIT {
COMPONENTS
w,r: PhaseSplitter,
ws, rs: CircularShifter[37],
inPass[37]: PassTransistor,
data: DataArray[16, 37],
sa, da: AndOr[2, 37],
saAnd, daAnd: And,
saInhibit, daInhibit: Inhibitor,
NODES dIn: ARRAY[1..37] OF Boolean,
sTemp, dTemp, siTemp, diTemp: Boolean
dw, dr: ARRAY[1..37] OF Boolean,
WR, WR’, RR, RR’: Boolean
REPRESENTATION
Din0, Din1, Din2, Din3, Din4, Din5, Din6, Din7, Din8, Din9, Din10,
Din11, Din12, Din13, Din14, Din15 ALIAS DataIn,
Dout0, Dout1, Dout2, Dout3, Dout4, Dout5, Dout6, Dout7, Dout8,
Dout9, Dout10, Dout11, Dout12, Dout13, Dout14, Dout15
ALIAS DataIn ####??##
CONNECTIONS
w[in: WriteRequest, out1: WR’, out2: WR],
r[in: ReadRequest, out1: RR’, out2: RR],

ws[init[1..37]: Init, inP1[1..37]: WR, inP2[1..37]: WR’, out: dw],
rs[init[1..37]: Init, inP1[1..37]: RR, inP2[1..37]: RR’, out: dr],

inPass(i)(in: DataIn(i), out: dIn(i), switch: WR’) | i IN 1..37,
data(input: dIn, output: DataOut, write: dw, read: dr),

sa(in(1): dw, in(2, 1..36): dr(2..37), in(2, 37): dr(1), out: sTemp),
da(in(1): dw, in(2): dr, out: dTemp),

saAnd(in1: sTemp, in2: siTemp, out: SpaceAv),
daAnd(in1: dTemp, in2: diTemp, out: DataAv),

saInhibit(in1: WR, in2: WR’, out: siTemp),
daInhibit(in1: RR, in2: RR’, out: diTemp)
}

We have assumed that the declarations of the following devices have been imported:
PassTransistor, PhaseSplitter, CircularShifter, DataArray,
Inhibitor, And, AndOr

Programs

The main program in Sakura will contain a circuit block. When this is executed it starts running, in turn starting off the devices mentioned in this circuit. These devices may themselves contain subcircuits which will then start running and so on.

A small example

A speaker sends a sequence of alternate trues and falses to a listener, who prints them.

BEGIN

speaker: DEVICE[n:CARDINAL] =
{
OUT out:Boolean
CONTROL
{FOR i IN [1..n] DO out ← TRUE; out ← FALSE ENDLOOP}
} ;

listener: DEVICE =
{
IN in: Boolean
CONTROL
DO WHEN in UP: writestring[ " up "];
WHEN in DOWN: writestring[ " down "];
ENDLOOP
};

CIRCUIT
{
COMPONENTS s: speaker[10], l:listener
NODES c: Boolean
CONNECTIONS s[out: c], l[in: c]
}

END