Machines
Machines are the first main concept in powdr-asm. They can currently be of two types: virtual or constrained.
Virtual machines
Dynamic machines are defined by:
- a degree range, indicating the number of execution steps
- a set of registers, including a program counter
- an instruction set
- a set of powdr-pil statements
- a set of functions
- a set of submachines
An example of a simple dynamic machine is the following:
machine HelloWorld with degree: 8 {
reg pc[@pc];
reg X[<=];
reg Y[<=];
reg A;
instr incr X -> Y {
Y = X + 1
}
instr decr X -> Y {
Y = X - 1
}
instr assert_zero X {
X = 0
}
function main {
// assign the first prover input to A
A <=X= ${ std::prelude::Query::Input(0, 1) };
// increment A
A <== incr(A);
// decrement A
A <== decr(A);
// assert that A is zero
assert_zero A;
return;
}
}
Constrained machines
Constrained machines are a lower-level type of machine. They do not have registers, and instead rely on simple committed and fixed columns. They are used to implement hand-optimized computation.
They are defined by:
- a degree range, indicating the number of execution steps
- a set of operations
- an
operation_identifier
column, used to make constraints conditional over which function is called. It can be omitted with_
if the machine has at most one operation. - a
latch
column, used to identify rows at which the machine can be accessed from the outside (where the inputs and outputs are passed). It can be omitted if the machine has no operations. - a set of submachines
- a set of links
An example of a simple constrained machine is the following:
machine SimpleStatic with
degree: 8,
latch: latch,
operation_id: operation_id
{
operation power_4<0> x -> y;
col fixed operation_id = [0]*;
col fixed latch = [0, 0, 0, 1]*;
col witness x;
col witness y;
// initialise y to x at the beginning of each block
latch * (y' - x') = 0;
// x is unconstrained at the beginning of the block
// x is constant within a block
(1 - latch) * (x' - x) = 0;
// y is multiplied by x at each row
(1 - latch) * (y' - x * y) = 0;
}
For more details on the powdr-pil statements, check out the pil section of this book. Note that the parameters of the operation are columns defined in powdr-pil statements.
Submachines
Machines can have submachines which they access by defining external instructions or links. They are declared as follows:
machine MySubmachine {
...
}
machine MyMachine {
MySubmachine my_submachine;
}
Machines can also receive submachines as construction parameters. A machine passed in as an argument can be accessed in the same way as locally declared submachines:
machine MachineWithParam(subm: MySubmachine) {
// `subm` can be accessed as a submachine
...
}
machine MyMachine {
MySubmachine my_submachine;
// `my_submachine` is passed to `another_submachine` as a construction argument
MachineWithParam another_submachine(my_submachine);
}