A Spreadsheet CLI

Can a spreadsheet be a programming language?

A Spreadsheet CLI

This section starts the effort of writing a spreadsheet geared toward implementing state machines. The requirements given in the previous section help define a cell's data structure and to define the commands to edit the fields in that data structure. Several open source spreadsheets were considered but all were rejected since all of them would have required extensive changes. Instead we are building the state machine spreadsheet from scratch.

If you think a little about a spreadsheet you might agree that model-view-controller paradigm fits it fairly well. The model is a two dimensional array of cell. The controller is the set of commands that manipulate the data in the cells, and the viewer let you watch the cells as the controller updates them.

On this page we describe the model and the controller, leaving the viewer for later. It might not be obvious but the viewer is actually optional. You could create a spreadsheet and let it run without seeing the cells update in real time. Github has a number of so-called "CLI spreadsheets."

The Model
Rows and columns have attributes, but it is the cell that really defines the capabilities of a spreadsheet. The SSM cell data structure is summarized below. The fields of this structure are not particularly dependent on the implementation language.

FieldUsage

value

integer value of the cell

width

bit width of value

nextval

an expression to compute the next value

type

cell type as logic, macro, register, or unused

initial

cell value at reset or program start

label

optional name of a cell

comment

describes the purpose of the cell

The value field is a read-only 64 bit unsigned integer. This field drives all logic and computation in the spreadsheet. You can not set a value directly as is it assigned from the result of the nextval computation.

The width field specifies the number of valid bits in value. All higher bits are set to zero as the last step in the nextval computation.

The nextval field is an algebraic formula that computes the value of the cell. Allowable bit operations include AND, OR, XOR, and NOT. Allowable arithmetic operations include addition and subtraction but not multiplication or division. Comparison operators include ==, !=, <, >, >=, and <=. The nextval formula may span several lines.

The type of a cell specifies when the value of a cell is valid. A "register" type sets the value at the end of a cycle. A "logic" or "macro" type assigns value the computed value of nextval at the start of a cycle. A macro is a logic block that takes one argument. To avoid computation loops, the nextval formula for logic and macros can only use register types in the computation. The default type is "unused" which marks the cell as needing no computation.

The initial field set the value at program start or at a reset. It is a 64 bit unsigned integer that is ANDed with a mask set by the width of the cell.

Like many spreadsheets, the columns are designated with a alphabetic letter and the rows with a decimal number. The fields are specified by the cell address "dot" field name. "A21.value" and "b10.nextval" are examples. A label is a shorthand way to specify a cell. For example, if cell A21 had a label of "count" then you could specify the nextval of A21 as ".count.nextval". A label not followed by a field name implies the value field. Thus A21.value could be written as ".count".

The model for the state machine spreadsheet is an array of cells that describe the current value, the next value, the initial value, the resolution of the value, and a comment about the cell. All values are updated in each "pass" through the spreadsheet. Each pass should correspond to one loop iteration of a Von Neumann program or one clock cycle of a Verilog state machine.

The Controller
The state machine spreadsheet controller consists of the commands to load, store, and run the spreadsheet, as well as the commands to set the fields of the cells. The meaning of the commands should be fairly obvious from the syntax of the command. In the list below an <expr> is an arithmetic expression and <string> is an ASCII string.

CommandMeaning

load <filename>;

Read sheet from file

save <filename>;

Save sheet to file

export verilog <filename>;

Export sheet to Verilog

export c <filename>;

Export sheet to C

export python <filename>;

Export sheet to Python

run <expr>;

Run until <expr> is zero

quit;

Exit spreadsheet program

reset;

Reinitialize all cell values

<cell_id>.nextval = <expr>;

Set nextval field

<cell_id>.width = <integer>;

Set bit width of cell

<cell_id>.initial = <integer>;

Set initial value

<cell_id>.label = <string>;

Define a label for the cell

<cell_id>.comment = <string>;

Add a comment to cell

<cell_id>.type = <register|logic|macro|unused>;

Set cell type

<cell_id>.nextval = <expr>;

Set nextval field

The expression in the run command can be a logic expression that evaluates as zero or one. You can use run and a logic expression as a way to set a breakpoint.

All commands end with a semicolon. Newlines, spaces, and tabs within an expression are preserved when saving.

The Towers of Hanoi puzzle from the previous sections is available here (toh.ssm) as a state machine spreadsheet. The excerpt from toh.ssm below illustrates a typical cell definition.

b1.comment = "Integer bit field for stack A";
b1.initial = 0xffffffff;
b1.nextval = (.A2B) ? .A & ~.TOSA :
             (.A2C) ? .A & ~.TOSA :
             (.B2A) ? .A | .TOSB :
             (.C2A) ? .A | .TOSC :
             .A;
b1.type = register;
b1.label = "A";
b1.width = 32;

Yacc and Lex
A yacc and lex (actually bison and flex) parser is available as (ssm.tgz). This just parses the commands but does not execute them. You can build and test the parser by installing bison and flex using these commands:

  tar -xf ssm.tgz
  cd ssm
  sudo apt-get install bison flex
  make

The above should give you an executable called ssm. Test the parser with the command:

  ./ssm < toh.ssm

Currently the parser uses right recursion. This may change in the next iteration.

Posted by Bob Smith | on