Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
ec4c118
Field VM, first edition
RobinJadoul Sep 8, 2026
555273b
Silly oversights
RobinJadoul Sep 8, 2026
58c27bc
Typechecker working for opaque types (as generalization of ExtField)
RobinJadoul Sep 8, 2026
2faf1a5
Make ruff happier
RobinJadoul Sep 8, 2026
ef1754c
Various fixes
RobinJadoul Sep 8, 2026
11a2714
Fix input hinting constraints to take hint_input from the next row
RobinJadoul Sep 8, 2026
341095d
Apply batched suggestions from code review
RobinJadoul Sep 10, 2026
6aeb08c
Improve expression rendering
RobinJadoul Sep 14, 2026
c6b01be
Field is not a code-term in the titles, imo
RobinJadoul Sep 14, 2026
a379d1b
Rename o register to d
RobinJadoul Sep 14, 2026
8801555
More elaborate VM architecture to intro
RobinJadoul Sep 14, 2026
a324367
Instructions vs states
RobinJadoul Sep 15, 2026
eb6ba7b
Registers and hinting
RobinJadoul Sep 15, 2026
3ec0b12
pseudoinstructions as a table
RobinJadoul Sep 15, 2026
b51f372
Clarify negative offsets into frame
RobinJadoul Sep 15, 2026
2ce4437
clarify syntactic degree being too high for mux
RobinJadoul Sep 15, 2026
3e81f92
typo
RobinJadoul Sep 15, 2026
c600a7e
Switch everything to next(...) notation
RobinJadoul Sep 15, 2026
2e025fb
Compression in the decode lookup
RobinJadoul Sep 17, 2026
23831be
padding
RobinJadoul Sep 17, 2026
f6a95ca
Decode table
RobinJadoul Sep 17, 2026
04d3f35
Minor
RobinJadoul Sep 17, 2026
932d58c
Don't line-break inline equations by default
RobinJadoul Sep 21, 2026
2061697
deg notation
RobinJadoul Sep 21, 2026
576e0c6
Apply batched suggestions from code review
RobinJadoul Sep 21, 2026
5d7555e
Clarify some writing
RobinJadoul Sep 21, 2026
06be08a
Comments on CALL/RET
RobinJadoul Sep 21, 2026
99a988f
Expand degree split differently
RobinJadoul Sep 21, 2026
d9af179
review
RobinJadoul Sep 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions spec/chapters/ecsm.typ
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

#let config = load_config()

#show math.equation.where(block: false): box

#let ecsm_chip = load_chip("src/ecsm.toml", config)
#let ecsm = raw(ecsm_chip.name)

Expand Down
1 change: 0 additions & 1 deletion spec/chapters/field.typ

This file was deleted.

2 changes: 0 additions & 2 deletions spec/chapters/field_decode.typ

This file was deleted.

340 changes: 340 additions & 0 deletions spec/chapters/field_vm.typ
Comment thread
erik-3milabs marked this conversation as resolved.

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions spec/chapters/field_vm_decode.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#import "/src.typ": load_config, load_chip
#import "/chip.typ": render_chip_variable_table, render_constraint_table
#let config = load_config()
#let chip = load_chip("/src/field_vm_decode.toml", config)
#let decode = raw(chip.name)

In this chapter, we provide a brief overview of the #decode chip,
that corresponds to the instruction decoding for @field-VM.
As the ISA from @field-VM:sec:isa was designed to have a simple mapping
onto AIR tables, the decoding table is itself also simple.

We present the table in its uncompressed form, but in practice, any
implementation would materialize the _virtual_ and _multiplicity_ columns only,
similar to the approach in @decode.
Due to its relative simplicity, we do not present both compressed and uncompressed
variants of the table separately.

= Variables

#render_chip_variable_table(chip, config)

= Constraints

#render_constraint_table(chip, config)
1 change: 0 additions & 1 deletion spec/chapters/limbs_and_carries.typ
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// Equation formatting
#show: equate.with(breakable: true, sub-numbering: true, number-mode: "label")
#set math.equation(numbering: "(1.1)")
#show math.equation.where(block: false): box

In this section, we discuss, in order,
+ the multiplication and addition of limb-decomposed integers (involving carries),
Expand Down
2 changes: 0 additions & 2 deletions spec/chapters/recursion.typ
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
#let prob = $PP$
#let to = math.arrow.r

#show math.equation.where(block: false): box

#set list(marker: [---])

= Proof recursion <proof-recursion>
Expand Down
48 changes: 28 additions & 20 deletions spec/expr.typ
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
// | ["-", expr] ; -expr
// | ["-", expr1, expr2, ...] ; expr1 - expr2 - ...
// | ["cast", expr, type] ; expr as type
// | ["next", var] ; var'
//
//
// To limit the number of parentheses that are placed in an expression,
Expand All @@ -54,19 +55,20 @@

#let PREC = (
"MIN": -1, // <the most secret heart of any expression>
"idx": 0, // []
"pow": 1, // ^
"neg": 2, // Unary -
"cast": 3, // cast
"mul": 4, // *
"div": 5, // /
"mod": 6, // mod
"sum": 7, // Σ
"not": 8, // not
"sub": 9, // -
"add": 10, // +
"eq": 11, // = and :=
"MAX": 12, // <the void outside every expression>
"next": 0, // var'
"idx": 1, // []
"pow": 2, // ^
"neg": 3, // Unary -
"cast": 4, // cast
"mul": 5, // *
"div": 6, // /
"mod": 7, // mod
"sum": 8, // Σ
"not": 9, // not
"sub": 10, // -
"add": 11, // +
"eq": 12, // = and :=
"MAX": 13, // <the void outside every expression>
)

// Mutual recursion through a trick from https://github.com/typst/typst/issues/744
Expand Down Expand Up @@ -114,7 +116,7 @@
`⧼` + raw(e.at(1)) + `⧽`
},
"arr": (pp, rec, e) => `[` + e.slice(1).map(rec.with(PREC.MAX)).join(`, `) + `]`,
"idx": (pp, rec, e) => rec(PREC.MIN, e.at(1)) + `[` + rec(PREC.MAX, e.at(2)) + `]`,
"idx": (pp, rec, e) => cwrap(rec(PREC.idx, e.at(1)) + `[` + rec(PREC.MAX, e.at(2)) + `]`, pp < PREC.idx),
"not": (pp, rec, e) => cwrap(rec(PREC.not, 1) + ` - ` + rec(PREC.not, e.at(1)), pp < PREC.not),
"+": (pp, rec, e) => cwrap(e.slice(1).map(rec.with(PREC.add)).join(` + `), pp < PREC.add),
"sum": (pp, rec, e) => assert(false, message: "sum is unsupported in code."),
Expand All @@ -136,9 +138,8 @@
},
"/": (pp, rec, e) => cwrap(rec(PREC.div, e.at(1)), pp < PREC.div) + ` / ` + rec(PREC.div, e.at(2)),
"^": (pp, rec, e) => {
assert(type(e.at(1)) == int and type(e.at(2)) == int, message: "Can only exponentiate constants")
// technically wrong associativity, but it's a constant
rec(PREC.pow, e.at(1)) + `^` + rec(PREC.pow, e.at(2))
// `<=` in the wrap to deal with right associativity
cwrap(rec(PREC.pow, e.at(1)) + `^` + rec(PREC.pow, e.at(2)), pp <= PREC.pow)
},
"=": (pp, rec, e) => rec(PREC.eq, e.at(1)) + ` = ` + rec(PREC.eq, e.at(2)),
":=": (pp, rec, e) => rec(PREC.eq, e.at(1)) + ` := ` + rec(PREC.eq, e.at(2)),
Expand All @@ -155,6 +156,10 @@
assert(e.len() == 3, message: "Invalid type cast: " + repr(e))
cwrap(rec(PREC.cast, e.at(1)) + ` as ` + type_to_code(e.at(2)), pp < PREC.cast)
},
"next": (pp, rec, e) => {
assert(e.len() == 2 and type(e.at(1)) == str, message: "Invalid transition variable: " + repr(e))
cwrap(rec(PREC.next, e.at(1)) + `'`, pp < PREC.next)
},
),
num: (n) => raw(str(n)),
flatten: flatten_code
Expand Down Expand Up @@ -217,8 +222,7 @@
},
"/": (pp, rec, e) => $#rec(PREC.div, e.at(1)) / #rec(PREC.div, e.at(2))$,
"^": (pp, rec, e) => {
assert(type(e.at(1)) == int, message: "Can only exponentiate constants")
$#e.at(1)^#rec(PREC.MAX, e.at(2))$
mwrap($#rec(PREC.pow, e.at(1))^#rec(PREC.MAX, e.at(2))$, pp <= PREC.pow)
},
"=": (pp, rec, e) => $#rec(PREC.eq, e.at(1)) = #rec(PREC.eq, e.at(2))$,
":=": (pp, rec, e) => $#rec(PREC.eq, e.at(1)) := #rec(PREC.eq, e.at(2))$,
Expand All @@ -236,7 +240,11 @@
},
"cast": (pp, rec, e) => {
assert(e.len() == 3, message: "Invalid type cast: " + repr(e))
cwrap($#rec(PREC.cast, e.at(1)) colon.double #type_to_math(e.at(2))$, pp < PREC.cast)
mwrap($#rec(PREC.cast, e.at(1)) colon.double #type_to_math(e.at(2))$, pp < PREC.cast)
},
"next": (pp, rec, e) => {
assert(e.len() == 2 and type(e.at(1)) == str, message: "Invalid transition variable: " + repr(e))
mwrap($#rec(PREC.next, e.at(1))'$, pp < PREC.next)
},
),
var: v => if v.len() == 1 { $#v$ } else { $#raw(v)$ },
Expand Down
5 changes: 3 additions & 2 deletions spec/meta.typ
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@
)),
("RECURSION", (
("recursion", [Recursive verification], <recursion>),
("field", [`Field` VM], <field-VM>),
("field_decode", [`Field` `DECODE` table], <field-decode>),
("field_vm", [Field VM], <field-VM>),
("field_vm_decode", [Field `DECODE` table], <field-decode>),
)),
("MATHEMATICS", (
("limbs_and_carries", [On limb decomposition and carries], <limbs>),
Expand Down Expand Up @@ -105,6 +105,7 @@
#let common-formatting(body) = {
set footnote(numbering: "[1]")
show raw.where(block: true): it => block(it, inset: 1em, width: 100%, radius: 5pt)
show math.equation.where(block: false): box // Don't line-break inline equations by default
show ref: equate.with(sub-numbering: true, breakable: true, number-mode: "label")
show selector.or(..highlights.keys().map(k => figure.where(kind: k))): it => {
set figure.caption(position: top)
Expand Down
5 changes: 5 additions & 0 deletions spec/src/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ subtypes = ["BaseField"]
range = [0, "18446744069414584320"]
desc = "Variable that can assume any value in the base field."

[[variables.types]]
label = "ExtField"
subtypes = ["ExtField"]
desc = "Variables that can assume any value in the extension field."

[[variables.types]]
label = "Bit"
subtypes = ["BaseField"]
Expand Down
Loading
Loading