kimchi/circuits/
wires.rs

1//! This module implements Plonk circuit gate wires primitive.
2
3use core::array;
4use serde::{Deserialize, Serialize};
5
6/// Number of registers
7pub const COLUMNS: usize = 15;
8
9/// Number of registers that can be wired (participating in the permutation)
10pub const PERMUTS: usize = 7;
11
12/// index of all registers
13pub const WIRES: [usize; COLUMNS] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
14
15/// Wire documents the other cell that is wired to this one.
16/// If the cell represents an internal wire, an input to the circuit,
17/// or a final output of the circuit, the cell references itself.
18#[derive(PartialEq, Default, Eq, Clone, Copy, Debug, Serialize, Deserialize)]
19#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
20#[cfg_attr(feature = "wasm_types", wasm_bindgen::prelude::wasm_bindgen)]
21pub struct Wire {
22    // TODO(mimoo): shouldn't we use u32 since we serialize them as u32?
23    pub row: usize,
24    pub col: usize,
25}
26
27impl Wire {
28    /// Creates a new [Wire].
29    pub fn new(row: usize, col: usize) -> Self {
30        Self { row, col }
31    }
32
33    /// Creates a new set of wires for a given row.
34    pub fn for_row(row: usize) -> [Self; PERMUTS] {
35        GateWires::new(row)
36    }
37}
38
39/// `GateWires` document the wiring of a gate. More specifically, each value either
40/// represents the same cell (row and column) or a different cell in another row.
41/// (This is to help the permutation argument.)
42pub type GateWires = [Wire; PERMUTS];
43
44/// Since we don't have a specific type for the wires of a row,
45/// we have to implement these convenience functions through a trait.
46pub trait Wirable: Sized {
47    /// Creates a new set of wires for a given row.
48    fn new(row: usize) -> Self;
49
50    /// Wire the cell at `col` to another cell (`to`).
51    fn wire(self, col: usize, to: Wire) -> Self;
52}
53
54impl Wirable for GateWires {
55    fn new(row: usize) -> Self {
56        array::from_fn(|col| Wire { row, col })
57    }
58
59    fn wire(mut self, col: usize, to: Wire) -> Self {
60        assert!(col < PERMUTS);
61        self[col] = to;
62        self
63    }
64}
65
66#[cfg(feature = "ocaml_types")]
67pub mod caml {
68    use super::*;
69    use core::convert::TryInto;
70
71    #[derive(ocaml::IntoValue, ocaml::FromValue, ocaml_gen::Struct)]
72    pub struct CamlWire {
73        pub row: ocaml::Int,
74        pub col: ocaml::Int,
75    }
76
77    impl From<Wire> for CamlWire {
78        fn from(w: Wire) -> Self {
79            Self {
80                row: w.row.try_into().expect("usize -> isize"),
81                col: w.col.try_into().expect("usize -> isize"),
82            }
83        }
84    }
85
86    impl From<CamlWire> for Wire {
87        fn from(w: CamlWire) -> Self {
88            Self {
89                row: w.row.try_into().expect("isize -> usize"),
90                col: w.col.try_into().expect("isize -> usize"),
91            }
92        }
93    }
94}
95
96#[cfg(feature = "wasm_types")]
97pub mod wasm {
98    use super::*;
99
100    #[wasm_bindgen::prelude::wasm_bindgen]
101    impl Wire {
102        #[wasm_bindgen::prelude::wasm_bindgen]
103        pub fn create(row: i32, col: i32) -> Self {
104            Self {
105                row: row as usize,
106                col: col as usize,
107            }
108        }
109    }
110}