mirror of https://github.com/zcash/halo2.git
Distinguish between selectors and all other columns in layouter using RegionColumn.
This commit is contained in:
parent
4283713ec7
commit
dfbd5e3332
|
@ -7,11 +7,11 @@ use ff::Field;
|
|||
|
||||
use crate::{
|
||||
circuit::{
|
||||
layouter::{RegionLayouter, RegionShape},
|
||||
layouter::{RegionColumn, RegionLayouter, RegionShape},
|
||||
Cell, Layouter, Region, RegionIndex, RegionStart,
|
||||
},
|
||||
plonk::{
|
||||
Advice, Any, Assigned, Assignment, Circuit, Column, Error, Fixed, FloorPlanner, Instance,
|
||||
Advice, Assigned, Assignment, Circuit, Column, Error, Fixed, FloorPlanner, Instance,
|
||||
Selector,
|
||||
},
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ pub struct SingleChipLayouter<'a, F: Field, CS: Assignment<F> + 'a> {
|
|||
/// Stores the starting row for each region.
|
||||
regions: Vec<RegionStart>,
|
||||
/// Stores the first empty row for each column.
|
||||
columns: HashMap<Column<Any>, usize>,
|
||||
columns: HashMap<RegionColumn, usize>,
|
||||
_marker: PhantomData<F>,
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ use ff::Field;
|
|||
|
||||
use crate::{
|
||||
circuit::{
|
||||
layouter::{RegionLayouter, RegionShape},
|
||||
layouter::{RegionColumn, RegionLayouter, RegionShape},
|
||||
Cell, Layouter, Region, RegionIndex, RegionStart,
|
||||
},
|
||||
plonk::{
|
||||
Advice, Assigned, Assignment, Circuit, Column, Error, Fixed, FloorPlanner, Instance,
|
||||
Advice, Any, Assigned, Assignment, Circuit, Column, Error, Fixed, FloorPlanner, Instance,
|
||||
Selector,
|
||||
},
|
||||
};
|
||||
|
@ -89,7 +89,7 @@ impl FloorPlanner for V1 {
|
|||
(
|
||||
c,
|
||||
column_allocations
|
||||
.get(&c.into())
|
||||
.get(&Column::<Any>::from(c).into())
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
|
|
|
@ -4,11 +4,8 @@ use std::{
|
|||
ops::Range,
|
||||
};
|
||||
|
||||
use super::RegionShape;
|
||||
use crate::{
|
||||
circuit::RegionStart,
|
||||
plonk::{Any, Column},
|
||||
};
|
||||
use super::{RegionColumn, RegionShape};
|
||||
use crate::{circuit::RegionStart, plonk::Any};
|
||||
|
||||
/// A region allocated within a column.
|
||||
#[derive(Clone, Default, Debug, PartialEq, Eq)]
|
||||
|
@ -102,14 +99,14 @@ impl Allocations {
|
|||
}
|
||||
|
||||
/// Allocated rows within a circuit.
|
||||
pub type CircuitAllocations = HashMap<Column<Any>, Allocations>;
|
||||
pub type CircuitAllocations = HashMap<RegionColumn, Allocations>;
|
||||
|
||||
/// - `start` is the current start row of the region (not of this column).
|
||||
/// - `slack` is the maximum number of rows the start could be moved down, taking into
|
||||
/// account prior columns.
|
||||
fn first_fit_region(
|
||||
column_allocations: &mut CircuitAllocations,
|
||||
region_columns: &[Column<Any>],
|
||||
region_columns: &[RegionColumn],
|
||||
region_length: usize,
|
||||
start: usize,
|
||||
slack: Option<usize>,
|
||||
|
@ -207,7 +204,10 @@ pub fn slot_in_biggest_advice_first(
|
|||
let advice_cols = shape
|
||||
.columns()
|
||||
.iter()
|
||||
.filter(|c| matches!(c.column_type(), Any::Advice))
|
||||
.filter(|c| match c {
|
||||
RegionColumn::Column(c) => matches!(c.column_type(), Any::Advice),
|
||||
_ => false,
|
||||
})
|
||||
.count();
|
||||
// Sort by advice area (since this has the most contention).
|
||||
advice_cols * shape.row_count()
|
||||
|
@ -226,23 +226,30 @@ pub fn slot_in_biggest_advice_first(
|
|||
|
||||
#[test]
|
||||
fn test_slot_in() {
|
||||
use crate::plonk::Column;
|
||||
|
||||
let regions = vec![
|
||||
RegionShape {
|
||||
region_index: 0.into(),
|
||||
columns: vec![Column::new(0, Any::Advice), Column::new(1, Any::Advice)]
|
||||
.into_iter()
|
||||
.map(|a| Column::<Any>::from(a).into())
|
||||
.collect(),
|
||||
row_count: 15,
|
||||
},
|
||||
RegionShape {
|
||||
region_index: 1.into(),
|
||||
columns: vec![Column::new(2, Any::Advice)].into_iter().collect(),
|
||||
columns: vec![Column::new(2, Any::Advice)]
|
||||
.into_iter()
|
||||
.map(|a| Column::<Any>::from(a).into())
|
||||
.collect(),
|
||||
row_count: 10,
|
||||
},
|
||||
RegionShape {
|
||||
region_index: 2.into(),
|
||||
columns: vec![Column::new(2, Any::Advice), Column::new(0, Any::Advice)]
|
||||
.into_iter()
|
||||
.map(|a| Column::<Any>::from(a).into())
|
||||
.collect(),
|
||||
row_count: 10,
|
||||
},
|
||||
|
|
|
@ -110,10 +110,49 @@ pub trait RegionLayouter<F: Field>: fmt::Debug {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct RegionShape {
|
||||
pub(super) region_index: RegionIndex,
|
||||
pub(super) columns: HashSet<Column<Any>>,
|
||||
pub(super) columns: HashSet<RegionColumn>,
|
||||
pub(super) row_count: usize,
|
||||
}
|
||||
|
||||
/// The virtual column involved in a region. This includes normal "logical"
|
||||
/// columns as well as selectors that are not definite columns at this stage.
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug, Hash)]
|
||||
pub enum RegionColumn {
|
||||
/// Logical column
|
||||
Column(Column<Any>),
|
||||
/// Virtual column representing a (boolean) selector
|
||||
Selector(Selector),
|
||||
}
|
||||
|
||||
impl From<Column<Any>> for RegionColumn {
|
||||
fn from(column: Column<Any>) -> RegionColumn {
|
||||
RegionColumn::Column(column)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Selector> for RegionColumn {
|
||||
fn from(selector: Selector) -> RegionColumn {
|
||||
RegionColumn::Selector(selector)
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for RegionColumn {
|
||||
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
||||
match (self, other) {
|
||||
(Self::Column(ref a), Self::Column(ref b)) => a.cmp(b),
|
||||
(Self::Selector(ref a), Self::Selector(ref b)) => a.0.cmp(&b.0),
|
||||
(Self::Column(_), Self::Selector(_)) => cmp::Ordering::Greater,
|
||||
(Self::Selector(_), Self::Column(_)) => cmp::Ordering::Less,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for RegionColumn {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl RegionShape {
|
||||
/// Create a new `RegionShape` for a region at `region_index`.
|
||||
pub fn new(region_index: RegionIndex) -> Self {
|
||||
|
@ -130,7 +169,7 @@ impl RegionShape {
|
|||
}
|
||||
|
||||
/// Get a reference to the set of `columns` used in a `RegionShape`.
|
||||
pub fn columns(&self) -> &HashSet<Column<Any>> {
|
||||
pub fn columns(&self) -> &HashSet<RegionColumn> {
|
||||
&self.columns
|
||||
}
|
||||
|
||||
|
@ -148,8 +187,7 @@ impl<F: Field> RegionLayouter<F> for RegionShape {
|
|||
offset: usize,
|
||||
) -> Result<(), Error> {
|
||||
// Track the selector's fixed column as part of the region's shape.
|
||||
// TODO: Avoid exposing selector internals?
|
||||
self.columns.insert(selector.0.into());
|
||||
self.columns.insert((*selector).into());
|
||||
self.row_count = cmp::max(self.row_count, offset + 1);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -161,7 +199,7 @@ impl<F: Field> RegionLayouter<F> for RegionShape {
|
|||
offset: usize,
|
||||
_to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
||||
) -> Result<Cell, Error> {
|
||||
self.columns.insert(column.into());
|
||||
self.columns.insert(Column::<Any>::from(column).into());
|
||||
self.row_count = cmp::max(self.row_count, offset + 1);
|
||||
|
||||
Ok(Cell {
|
||||
|
@ -190,7 +228,7 @@ impl<F: Field> RegionLayouter<F> for RegionShape {
|
|||
advice: Column<Advice>,
|
||||
offset: usize,
|
||||
) -> Result<(Cell, Option<F>), Error> {
|
||||
self.columns.insert(advice.into());
|
||||
self.columns.insert(Column::<Any>::from(advice).into());
|
||||
self.row_count = cmp::max(self.row_count, offset + 1);
|
||||
|
||||
Ok((
|
||||
|
@ -210,7 +248,7 @@ impl<F: Field> RegionLayouter<F> for RegionShape {
|
|||
offset: usize,
|
||||
_to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
||||
) -> Result<Cell, Error> {
|
||||
self.columns.insert(column.into());
|
||||
self.columns.insert(Column::<Any>::from(column).into());
|
||||
self.row_count = cmp::max(self.row_count, offset + 1);
|
||||
|
||||
Ok(Cell {
|
||||
|
|
Loading…
Reference in New Issue