Skip to content

Commit

Permalink
dev: Add halo2::dev::render_to_json API
Browse files Browse the repository at this point in the history
This exposes the internally-collected data used by CircuitLayout, to
enable alternative external visualisations.
  • Loading branch information
str4d committed Apr 1, 2023
1 parent 42ea711 commit 2d4d95e
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 3 deletions.
4 changes: 3 additions & 1 deletion halo2_proofs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ maybe-rayon = {version = "0.1.0", default-features = false}

# Developer tooling dependencies
plotters = { version = "0.3.0", default-features = false, optional = true }
serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }
tabbycat = { version = "0.1", features = ["attributes"], optional = true }

# Legacy circuit compatibility
Expand All @@ -73,7 +75,7 @@ getrandom = { version = "0.2", features = ["js"] }
[features]
default = ["batch", "multicore"]
multicore = ["maybe-rayon/threads"]
dev-graph = ["plotters", "tabbycat"]
dev-graph = ["plotters", "serde", "serde_json", "tabbycat"]
test-dev-graph = [
"dev-graph",
"plotters/bitmap_backend",
Expand Down
1 change: 1 addition & 0 deletions halo2_proofs/src/circuit/layouter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ pub struct RegionShape {
/// The virtual column involved in a region. This includes concrete columns,
/// as well as selectors that are not concrete columns at this stage.
#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash)]
#[cfg_attr(feature = "dev-graph", derive(serde::Serialize))]
pub enum RegionColumn {
/// Concrete column
Column(Column<Any>),
Expand Down
5 changes: 4 additions & 1 deletion halo2_proofs/src/dev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ mod graph;

#[cfg(feature = "dev-graph")]
#[cfg_attr(docsrs, doc(cfg(feature = "dev-graph")))]
pub use graph::{circuit_dot_graph, layout::CircuitLayout};
pub use graph::{
circuit_dot_graph,
layout::{render_to_json, CircuitLayout},
};

#[derive(Debug)]
struct Region {
Expand Down
25 changes: 25 additions & 0 deletions halo2_proofs/src/dev/cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use std::{
use ff::{Field, PrimeField};
use group::prime::PrimeGroup;

#[cfg(feature = "dev-graph")]
use serde::ser::SerializeStruct;

use crate::{
circuit::{layouter::RegionColumn, Value},
plonk::{
Expand Down Expand Up @@ -54,7 +57,28 @@ pub struct CircuitCost<G: PrimeGroup, ConcreteCircuit: Circuit<G::Scalar>> {
_marker: PhantomData<(G, ConcreteCircuit)>,
}

#[cfg(feature = "dev-graph")]
impl serde::Serialize for Column<Any> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut state = serializer.serialize_struct("Column", 2)?;
state.serialize_field(
"kind",
match self.column_type() {
Any::Advice => "advice",
Any::Fixed => "fixed",
Any::Instance => "instance",
},
)?;
state.serialize_field("index", &self.index())?;
state.end()
}
}

#[derive(Debug)]
#[cfg_attr(feature = "dev-graph", derive(serde::Serialize))]
pub(crate) struct Cell {
pub(crate) column: RegionColumn,
pub(crate) row: usize,
Expand All @@ -63,6 +87,7 @@ pub(crate) struct Cell {
/// Region implementation used by Layout
#[allow(dead_code)]
#[derive(Debug)]
#[cfg_attr(feature = "dev-graph", derive(serde::Serialize))]
pub(crate) struct LayoutRegion {
/// The name of the region. Not required to be unique.
pub(crate) name: String,
Expand Down
35 changes: 34 additions & 1 deletion halo2_proofs/src/dev/graph/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ use plotters::{
coord::Shift,
prelude::{DrawingArea, DrawingAreaErrorKind, DrawingBackend},
};

use std::collections::HashSet;
use std::ops::Range;

use crate::{
circuit::layouter::RegionColumn,
dev::cost::{Cell, Layout},
dev::cost::{Cell, Layout, LayoutRegion},
plonk::{Any, Circuit, Column, ConstraintSystem, FloorPlanner},
};

Expand Down Expand Up @@ -318,3 +319,35 @@ impl CircuitLayout {
Ok(())
}
}

/// Renders the given circuit layout to a JSON string.
pub fn render_to_json<F: Field, ConcreteCircuit: Circuit<F>>(
circuit: &ConcreteCircuit,
) -> Result<String, serde_json::Error> {
// Collect the layout details.
let mut cs = ConstraintSystem::default();
let config = ConcreteCircuit::configure(&mut cs);
let mut layout = Layout::default();
ConcreteCircuit::FloorPlanner::synthesize(&mut layout, circuit, config, cs.constants).unwrap();

// Render.
#[derive(serde::Serialize)]
struct Circuit {
num_instance_columns: usize,
num_advice_columns: usize,
num_fixed_columns: usize,
total_rows: usize,
regions: Vec<LayoutRegion>,
loose_cells: Vec<Cell>,
selectors: Vec<Vec<bool>>,
}
serde_json::to_string(&Circuit {
num_instance_columns: cs.num_instance_columns,
num_advice_columns: cs.num_advice_columns,
num_fixed_columns: cs.num_fixed_columns,
total_rows: layout.total_rows,
regions: layout.regions,
loose_cells: layout.loose_cells,
selectors: layout.selectors,
})
}
1 change: 1 addition & 0 deletions halo2_proofs/src/plonk/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ impl TryFrom<Column<Any>> for Column<Instance> {
/// }
/// ```
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "dev-graph", derive(serde::Serialize))]
pub struct Selector(pub(crate) usize, bool);

impl Selector {
Expand Down

0 comments on commit 2d4d95e

Please sign in to comment.