mirror of https://github.com/zcash/halo2.git
Merge pull request #350 from zcash/fix-simple-floor-planner-constants
Fix SimpleFloorPlanner's handling of global constants
This commit is contained in:
commit
6d3a11511d
|
@ -101,14 +101,42 @@ impl<'a, F: Field, CS: Assignment<F> + 'a> Layouter<F> for SingleChipLayouter<'a
|
||||||
self.columns.insert(column, region_start + shape.row_count);
|
self.columns.insert(column, region_start + shape.row_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign region cells.
|
||||||
self.cs.enter_region(name);
|
self.cs.enter_region(name);
|
||||||
let mut region = SingleChipLayouterRegion::new(self, region_index.into());
|
let mut region = SingleChipLayouterRegion::new(self, region_index.into());
|
||||||
let result = {
|
let result = {
|
||||||
let region: &mut dyn RegionLayouter<F> = &mut region;
|
let region: &mut dyn RegionLayouter<F> = &mut region;
|
||||||
assignment(region.into())
|
assignment(region.into())
|
||||||
}?;
|
}?;
|
||||||
|
let constants_to_assign = region.constants;
|
||||||
self.cs.exit_region();
|
self.cs.exit_region();
|
||||||
|
|
||||||
|
// Assign constants. For the simple floor planner, we assign constants in order in
|
||||||
|
// the first `constants` column.
|
||||||
|
if self.constants.is_empty() {
|
||||||
|
if !constants_to_assign.is_empty() {
|
||||||
|
return Err(Error::NotEnoughColumnsForConstants);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let constants_column = self.constants[0];
|
||||||
|
let next_constant_row = self.columns.entry(constants_column.into()).or_default();
|
||||||
|
for (constant, advice) in constants_to_assign {
|
||||||
|
self.cs.assign_fixed(
|
||||||
|
|| format!("Constant({:?})", constant.evaluate()),
|
||||||
|
constants_column,
|
||||||
|
*next_constant_row,
|
||||||
|
|| Ok(constant),
|
||||||
|
)?;
|
||||||
|
self.cs.copy(
|
||||||
|
constants_column.into(),
|
||||||
|
*next_constant_row,
|
||||||
|
advice.column,
|
||||||
|
*self.regions[*advice.region_index] + advice.row_offset,
|
||||||
|
)?;
|
||||||
|
*next_constant_row += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +174,8 @@ impl<'a, F: Field, CS: Assignment<F> + 'a> Layouter<F> for SingleChipLayouter<'a
|
||||||
struct SingleChipLayouterRegion<'r, 'a, F: Field, CS: Assignment<F> + 'a> {
|
struct SingleChipLayouterRegion<'r, 'a, F: Field, CS: Assignment<F> + 'a> {
|
||||||
layouter: &'r mut SingleChipLayouter<'a, F, CS>,
|
layouter: &'r mut SingleChipLayouter<'a, F, CS>,
|
||||||
region_index: RegionIndex,
|
region_index: RegionIndex,
|
||||||
// The index of the next available row in the first constants column.
|
/// Stores the constants to be assigned, and the cells to which they are copied.
|
||||||
next_constant_row: usize,
|
constants: Vec<(Assigned<F>, Cell)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> fmt::Debug
|
impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> fmt::Debug
|
||||||
|
@ -166,7 +194,7 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> SingleChipLayouterRegion<'r, 'a,
|
||||||
SingleChipLayouterRegion {
|
SingleChipLayouterRegion {
|
||||||
layouter,
|
layouter,
|
||||||
region_index,
|
region_index,
|
||||||
next_constant_row: 0,
|
constants: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,17 +280,12 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F>
|
||||||
offset: usize,
|
offset: usize,
|
||||||
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
to: &'v mut (dyn FnMut() -> Result<Assigned<F>, Error> + 'v),
|
||||||
) -> Result<Cell, Error> {
|
) -> Result<Cell, Error> {
|
||||||
let row = *self.layouter.regions[*self.region_index] + offset;
|
self.layouter.cs.assign_fixed(
|
||||||
|
annotation,
|
||||||
self.layouter.cs.assign_fixed(annotation, column, row, to)?;
|
column,
|
||||||
|
*self.layouter.regions[*self.region_index] + offset,
|
||||||
if let Some(c) = self.layouter.constants.first() {
|
to,
|
||||||
if c == &column {
|
)?;
|
||||||
// Ensure that the next row we will assign a constant to is always after any
|
|
||||||
// prior assignments (for simplicity).
|
|
||||||
self.next_constant_row = cmp::max(self.next_constant_row, row + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Cell {
|
Ok(Cell {
|
||||||
region_index: self.region_index,
|
region_index: self.region_index,
|
||||||
|
@ -272,26 +295,8 @@ impl<'r, 'a, F: Field, CS: Assignment<F> + 'a> RegionLayouter<F>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error> {
|
fn constrain_constant(&mut self, cell: Cell, constant: Assigned<F>) -> Result<(), Error> {
|
||||||
if self.layouter.constants.is_empty() {
|
self.constants.push((constant, cell));
|
||||||
return Err(Error::NotEnoughColumnsForConstants);
|
Ok(())
|
||||||
}
|
|
||||||
|
|
||||||
// For the simple layouter, just assign the fixed constants inside the region
|
|
||||||
// using the first constants column. self.next_constant_row is updated by this
|
|
||||||
// function call.
|
|
||||||
let fixed = self.assign_fixed(
|
|
||||||
&|| "constant".into(),
|
|
||||||
self.layouter.constants[0],
|
|
||||||
// Convert the absolute row into a relative offset within this region, but
|
|
||||||
// always at an offset that is not before this region (taking advantage of the
|
|
||||||
// fact that for this single-pass layouter, regions are always laid out in
|
|
||||||
// increasing row order).
|
|
||||||
self.next_constant_row
|
|
||||||
.saturating_sub(*self.layouter.regions[*self.region_index]),
|
|
||||||
&mut || Ok(constant),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
self.constrain_equal(cell, fixed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
|
fn constrain_equal(&mut self, left: Cell, right: Cell) -> Result<(), Error> {
|
||||||
|
|
Loading…
Reference in New Issue