Follow VADCOP —1
Instructions
an instruction consists of:
- a name
- a set of inputs (assignment registers or labels)
- a set of outputs (assignment registers)
- a set of powdr-pil constraints to activate when the instruction is called
- a set of links calling into functions/operations in submachines
//name of the instruction, and four assignment register as inputs
instr mload X, Y, Z, W
These two link (call) sub-machine
link => bit2.check(tmp4_col)
link => bit6.check(X_b1)
=> and ~> is either permutation or lookup
The pil file generated from this asm file is
let me focus on the columns generated from the first instruction
constrains:
main.instr_mload * (main.tmp1_col + main.Y - (main.wrap_bit * 4294967296 + main.X_b4 * 16777216 + main.X_b3 * 65536 + main.X_b2 * 256 + main.X_b1 * 4 + main.tmp4_col)) = 0;
main.instr_mstore * (main.tmp1_col - main.tmp2_col + main.Z - (main.X_b1 + main.X_b2 * 256 + main.X_b3 * 65536 + main.X_b4 * 16777216 + main.wrap_bit * 4294967296)) = 0;
it constraints:
\(tmp_1+Y=wrap_{bit}\cdot 2^{32}+ x_{b4}\cdot 2^{24}+x_{b3}\cdot 2^{16}+x_{b2}\cdot 2^8+x_{b1}\cdot 2^2 +tmp_4\)
\(tmp_1-tmp_2+Z=x_{b1}+x_{b2}\cdot 2^8 +x_{b3}\cdot 2^{16}+x_{b4}\cdot 2^{24}+wrap_{bit}\cdot 2^{32} \)
….
okay, let return back a bit the VADCOP
this open issue is about logup, bus, sound
let’s check how the lookup is implemented
challenge in prover is defined like this
// let name: type type ->
let challenge: int, int -> expr = constr |st, id| std::prelude::challenge(st, id);
let unpack_lookup_constraint: Constr -> (expr, expr[], expr, expr[]) = |lookup_constraint| match lookup_constraint {
Constr::Lookup((lhs_selector, rhs_selector), values) => (
unwrap_or_else(lhs_selector, || 1),
map(values, |(lhs, _)| lhs),
unwrap_or_else(rhs_selector, || 1),
map(values, |(_, rhs)| rhs)
),
_ => panic("Expected lookup constraint")
};
get to know prelude.asm, many built-in types and values.
also specified in Modules section:
“Similar to Rust, any reference that cannot be resolved is looked up once more in std::prelude
. This module exposes basic types and values such as Option
, true
and false
. This means that you can use Option
anywhere without prefix.”
The lookup constraint is defined as below in prelude
/// A lookup constraint with selectors.
Lookup((Option<expr>, Option<expr>), (expr, expr)[]),
so in the test file, lookup constraint is declared as
let lookup_constraint = Constr::Lookup(
(Option::Some(random_six), Option::Some(first_seven)),
[(a1, b1), (a2, b2), (a3, b3)]
);
Match
The match syntax : match term {marching_term_1 => output1, matching_term_2 => output2 …}
example:
// The match statement typically uses patterns to check for certain values
// but it can also destructure and create new local variables valid inside
// the match arm.
let t = match (x, f((1, x), 2)) {
(0, _) => 0,
(1, _) => 7,
(_, y) => y,
_ => 9
};
Explanation:
- Match Statement:
- The
match
statement takes the tuple(x, f((1, x), 2))
as its input:x
is9
from the previous example.f((1, x), 2)
calls the functionf
with the arguments(1, 9)
and2
. This returns the tuple(1 + 2, 9)
, which is(3, 9)
.
- The
match
statement then evaluates this combined tuple(9, (3, 9))
against the provided patterns:(0, _) => 0
: If the first element is0
, return0
. This does not match.(1, _) => 7
: If the first element is1
, return7
. This does not match.(_, y) => y
: If the first element can be anything (_
), assign the second element toy
and returny
. In this case, the second element is(3, 9)
, soy
would be(3, 9)
._ => 9
: A catch-all pattern that returns9
. This will match if none of the above patterns do.
- Final Value of
t
: Since(9, (3, 9))
matches the pattern(_, y) => y
,t
will be assigned the value(3, 9)
.
- The
map
defined here
Explanation
1. Generic Type Parameters: <T1, T2>
<T1, T2>
: This part defines two generic type parameters,T1
andT2
. These generics allow themap
function to be flexible in terms of the types it can handle.T1
is the type of the elements in the input array.T2
is the type of the elements in the output array.
2. Function Type Signature: T1[], (T1 -> T2) -> T2[]
T1[]
: The functionmap
takes an array of typeT1
as its first parameter.(T1 -> T2)
: The second parameter is a functionf
that takes a single element of typeT1
and returns an element of typeT2
.T2[]
: The function returns an array of typeT2
.
Function Body: |arr, f| new(len(arr), |i| f(arr[i]))
|arr, f|
: This is the syntax for an anonymous function (or lambda). It takes two arguments:arr
: An array of typeT1
.f
: A function that maps elements from typeT1
to typeT2
.
new(len(arr), |i| f(arr[i]))
:new(len(arr), ...)
: Creates a new array with the same length asarr
.len(arr)
: Returns the length of the arrayarr
.|i| f(arr[i])
: This is another lambda function that is used to populate the elements of the new array:i
is the index of the array.arr[i]
accesses the element at indexi
in the arrayarr
.f(arr[i])
applies the functionf
to the elementarr[i]
, converting it from typeT1
to typeT2
.- The result of
f(arr[i])
is stored in the new array at indexi
.
Panic
defined here
Taking note in next post.