Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use RAM/ROM opcode when supported by the backend #1282

Merged
merged 57 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
bcb631d
assign a VM per array
guipublic Feb 13, 2023
4668c72
Merge branch 'master' into gd/dynamic_array4
guipublic Feb 13, 2023
520c2f9
cargo format
guipublic Feb 13, 2023
9764650
Code review
guipublic Feb 14, 2023
50e7d57
code review
guipublic Feb 14, 2023
6dbe6f6
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 14, 2023
528051b
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 20, 2023
8f8d0c5
enable dynamic arrays
guipublic Feb 21, 2023
b01a92c
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 21, 2023
2d51e6f
use trace index as counter
guipublic Feb 21, 2023
cb43e94
restore bad commit
guipublic Feb 21, 2023
c5a0bf9
restore bad commit
guipublic Feb 21, 2023
327fe57
restore bad commit
guipublic Feb 21, 2023
2aa2fb5
Code review
guipublic Feb 22, 2023
55afff4
Code review
guipublic Feb 23, 2023
e6eface
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 23, 2023
c23cefb
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 23, 2023
a027e74
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 24, 2023
af17ec6
Code review
guipublic Feb 28, 2023
36ca66c
Merge branch 'master' into gd/dynamic_array5
guipublic Feb 28, 2023
0c1bc4e
MemAddress
guipublic Feb 28, 2023
1e3861f
Merge branch 'master' into gd/dynamic_array5
guipublic Mar 10, 2023
352b447
Merge branch 'master' into gd/dynamic_array5
guipublic Mar 10, 2023
966b557
merge from master
guipublic Mar 10, 2023
ff90d69
Merge branch 'master' into gd/dynamic_array5
guipublic Mar 10, 2023
cb93f6e
Remove ilog2 because it is tagged as unstable
guipublic Mar 10, 2023
9002218
Merge branch 'master' into gd/dynamic_array5
guipublic Mar 14, 2023
c79e9dc
clippy
guipublic Mar 14, 2023
1aa52fe
*WIP* handle block opcode
guipublic Mar 16, 2023
713ebc3
**WIP** support RAM/ROM/BLOCK opcodes
guipublic Mar 21, 2023
4c29ec6
Merge branch 'master' into gd/dynamic_array9
guipublic Mar 22, 2023
a8e4aef
Merge branch 'master' into gd/dynamic_array9
guipublic May 3, 2023
9830b47
fikx the build after merge
guipublic May 3, 2023
78da427
clean-up
guipublic May 3, 2023
be1cf68
missed this one
guipublic May 3, 2023
0e1d447
Merge branch 'master' into gd/dynamic_array9
guipublic May 3, 2023
f9c2db8
code review
guipublic May 3, 2023
ad51715
code review
guipublic May 3, 2023
d58de5c
Fix issue with array_len
guipublic May 4, 2023
99bbc7a
Merge branch 'master' into gd/dynamic_array9
guipublic May 5, 2023
899df76
clarify comment
guipublic May 15, 2023
dab6bb3
code review
guipublic May 15, 2023
7be88eb
code review
guipublic May 15, 2023
075110d
Code review
guipublic May 15, 2023
6ac418a
Hardcode BB support for memory gates
guipublic May 25, 2023
dc0cf8f
Fix clippy error
guipublic May 25, 2023
3337cb5
Code review
guipublic May 25, 2023
ab6a3f3
Merge branch 'master' into gd/dynamic_array9
guipublic May 25, 2023
d887087
Check for array length before adding a memory gate
guipublic May 26, 2023
6cd3a70
avoid empty memory constraints
guipublic May 30, 2023
863f1fd
Merge branch 'master' into gd/dynamic_array9
guipublic Jun 2, 2023
9be7dc1
Merge branch 'master' into gd/dynamic_array9
guipublic Jun 2, 2023
837798a
Use correct trace length
guipublic Jun 2, 2023
150fe55
Merge branch 'master' into gd/dynamic_array9
guipublic Jun 12, 2023
91e376a
Create a witness for memory operations
guipublic Jun 12, 2023
01edbc3
use barretenberg with dynamic array fixes
guipublic Jun 13, 2023
b9d35b1
Update to last commit of bb noir branch, through flake.lock
guipublic Jun 14, 2023
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
126 changes: 117 additions & 9 deletions crates/noirc_evaluator/src/ssa/acir_gen/acir_mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,95 @@ impl ArrayHeap {
self.staged.insert(index, (value, op));
}

/// This helper function transforms an expression into a single witness representing the expression
fn normalize_expression(expr: &Expression, evaluator: &mut Evaluator) -> Expression {
expr.to_witness()
.unwrap_or_else(|| evaluator.create_intermediate_variable(expr.clone()))
.into()
}

/// Decide which opcode to use, depending on the backend support
fn acir_gen(
&self,
evaluator: &mut Evaluator,
array_id: ArrayId,
array_len: u32,
is_opcode_supported: OpcodeSupported,
) {
//sanity check
if array_len == 0 || self.trace.is_empty() {
return;
}
let dummy = MemoryBlock { id: AcirBlockId(0), len: 0, trace: Vec::new() };
let trace_len = match self.typ {
ArrayType::ReadOnly(Some(len)) | ArrayType::ReadWrite(Some(len)) => len,
_ => self.trace.len(),
};

if is_opcode_supported(&AcirOpcode::ROM(dummy.clone())) {
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
// If the backend support ROM and the array is read-only, we generate the ROM opcode
if matches!(self.typ, ArrayType::ReadOnly(_)) {
self.add_rom_opcode(evaluator, array_id, array_len, trace_len);
return;
}
}
if is_opcode_supported(&AcirOpcode::Block(dummy.clone())) {
self.add_block_opcode(evaluator, array_id, array_len);
} else if is_opcode_supported(&AcirOpcode::RAM(dummy)) {
self.add_ram_opcode(evaluator, array_id, array_len, trace_len);
} else {
self.generate_permutation_constraints(evaluator, array_id, array_len);
}
}

fn add_block_opcode(&self, evaluator: &mut Evaluator, array_id: ArrayId, array_len: u32) {
evaluator.opcodes.push(AcirOpcode::Block(MemoryBlock {
id: AcirBlockId(array_id.as_u32()),
len: array_len,
trace: self.trace.clone(),
}));
}

fn add_rom_opcode(
&self,
evaluator: &mut Evaluator,
array_id: ArrayId,
array_len: u32,
trace_len: usize,
) {
let mut trace = Vec::with_capacity(trace_len);
for op in self.trace.iter().take(trace_len) {
let index = Self::normalize_expression(&op.index, evaluator);
let value = Self::normalize_expression(&op.value, evaluator);
trace.push(MemOp { operation: op.operation.clone(), index, value });
}
evaluator.opcodes.push(AcirOpcode::ROM(MemoryBlock {
id: AcirBlockId(array_id.as_u32()),
len: array_len,
trace,
}));
}

fn add_ram_opcode(
&self,
evaluator: &mut Evaluator,
array_id: ArrayId,
array_len: u32,
trace_len: usize,
) {
let mut trace = Vec::with_capacity(trace_len);
for op in self.trace.iter().take(trace_len) {
let index = Self::normalize_expression(&op.index, evaluator);
let value = Self::normalize_expression(&op.value, evaluator);
trace.push(MemOp { operation: op.operation.clone(), index, value });
}
evaluator.opcodes.push(AcirOpcode::RAM(MemoryBlock {
id: AcirBlockId(array_id.as_u32()),
len: array_len,
trace,
}));
}

fn generate_outputs(
inputs: Vec<Expression>,
bits: &mut Vec<Witness>,
Expand All @@ -130,22 +219,21 @@ impl ArrayHeap {
}
outputs
}

pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, array_id: ArrayId, array_len: u32) {
fn generate_permutation_constraints(
&self,
evaluator: &mut Evaluator,
array_id: ArrayId,
array_len: u32,
) {
let (len, read_write) = match self.typ {
ArrayType::Init(_, _) | ArrayType::WriteOnly => (0, true),
ArrayType::ReadOnly(last) => (last.unwrap_or(self.trace.len()), false),
ArrayType::ReadWrite(last) => (last.unwrap_or(self.trace.len()), true),
};

if len == 0 {
return;
}
evaluator.opcodes.push(AcirOpcode::Block(MemoryBlock {
id: AcirBlockId(array_id.as_u32()),
len: array_len,
trace: self.trace.clone(),
}));
self.add_block_opcode(evaluator, array_id, array_len);
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
let len_bits = AcirMem::bits(len);
// permutations
let mut in_counter = Vec::new();
Expand Down Expand Up @@ -262,6 +350,17 @@ impl AcirMem {
}
}

//Ensure we do not optimise writes when the array is returned
pub(crate) fn return_array(&mut self, array_id: ArrayId) {
let heap = self.array_heap_mut(array_id);
match heap.typ {
ArrayType::ReadOnly(_) | ArrayType::ReadWrite(_) => {
heap.typ = ArrayType::ReadWrite(None);
}
_ => (),
}
}

// Load array values into InternalVars
pub(super) fn load_array(
&mut self,
Expand Down Expand Up @@ -327,9 +426,18 @@ impl AcirMem {
self.array_heap_mut(*array_id).push(item);
}
pub(crate) fn acir_gen(&self, evaluator: &mut Evaluator, ctx: &SsaContext) {
//Temporary hack - We hardcode Barretenberg support here.
//TODO: to remove once opcodesupported usage is clarified
let is_opcode_supported: OpcodeSupported = |o| match o {
AcirOpcode::Block(_) => false,
AcirOpcode::ROM(_) | AcirOpcode::RAM(_) => true,
_ => unreachable!(),
};
for mem in &self.virtual_memory {
let array = &ctx.mem[*mem.0];
mem.1.acir_gen(evaluator, array.id, array.len);
mem.1.acir_gen(evaluator, array.id, array.len, is_opcode_supported);
}
}
}

type OpcodeSupported = fn(&AcirOpcode) -> bool;
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) fn evaluate(
let objects = match Memory::deref(ctx, *node_id) {
Some(a) => {
let array = &ctx.mem[a];
memory_map.return_array(a);
memory_map.load_array(array, evaluator)
}
None => {
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.