Skip to content

Commit fc5b364

Browse files
authored
Fix precompiled assembly mem reads (#328)
* Fix precompiled assembly mem reads
1 parent 4ce030e commit fc5b364

File tree

6 files changed

+110
-22
lines changed

6 files changed

+110
-22
lines changed

core/src/zisk_rom.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -3286,16 +3286,13 @@ impl ZiskRom {
32863286
for j in 0..2 {
32873287
// For every indirection
32883288
for i in 0..indirections_count {
3289-
if i >= load_count {
3290-
break;
3291-
}
32923289
// Store next aligned address value in mem_reads, and advance it
32933290
*s += &format!(
32943291
"\tmov {}, [{} + {}*8] /* value = mem[address+{}] */\n",
32953292
REG_VALUE, REG_ADDRESS, i, i
32963293
);
32973294

3298-
// During the first iteration, store the indirectionread value in mem_reads
3295+
// During the first iteration, store the indirection read value in mem_reads
32993296
if j == 0 {
33003297
*s += &format!(
33013298
"\tmov [{} + {}*8 + {}*8], {} /* mem_reads[@+size*8+ind*8] = ind */\n",
@@ -3307,6 +3304,12 @@ impl ZiskRom {
33073304
// During the second iteration, store the first load_count iterations
33083305
// load_size elements in mem_reads
33093306
if j == 1 {
3307+
// Only store the first load_count indirections
3308+
if i >= load_count {
3309+
break;
3310+
}
3311+
3312+
// For each chunk of the indirection, store it in mem_reads
33103313
for l in 0..load_size {
33113314
*s += &format!(
33123315
"\tmov {}, [{} + {}*8] /* aux = mem[ind+{}] */\n",

emulator-asm/src/main.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -1226,36 +1226,36 @@ void log_trace(void)
12261226

12271227
// Log current chunk start state
12281228
printf("\tStart state:\n");
1229-
printf("\t\tpc=0x%lx:\n", chunk[i]);
1229+
printf("\t\tpc=0x%lx\n", chunk[i]);
12301230
i++;
1231-
printf("\t\tsp=0x%lx:\n", chunk[i]);
1231+
printf("\t\tsp=0x%lx\n", chunk[i]);
12321232
i++;
1233-
printf("\t\tc=0x%lx:\n", chunk[i]);
1233+
printf("\t\tc=0x%lx\n", chunk[i]);
12341234
i++;
1235-
printf("\t\tstep=%ld:\n", chunk[i]);
1235+
printf("\t\tstep=%ld\n", chunk[i]);
12361236
i++;
12371237
for (uint64_t r=1; r<34; r++)
12381238
{
1239-
printf("\t\tregister[%ld]=0x%ld:\n", r, chunk[i]);
1239+
printf("\t\tregister[%ld]=0x%lx\n", r, chunk[i]);
12401240
i++;
12411241
}
12421242

12431243
// Log current chunk last state
12441244
printf("\tLast state:\n");
1245-
printf("\t\tc=0x%lx:\n", chunk[i]);
1245+
printf("\t\tc=0x%lx\n", chunk[i]);
12461246
i++;
12471247

12481248
// Log current chunk end
12491249
printf("\tEnd:\n");
1250-
printf("\t\tend=%ld:\n", chunk[i]);
1250+
printf("\t\tend=%ld\n", chunk[i]);
12511251
i++;
12521252

12531253
// Log current chunk steps
12541254
printf("\tSteps:\n");
1255-
printf("\t\tsteps=%ld:\n", chunk[i]);
1255+
printf("\t\tsteps=%ld\n", chunk[i]);
12561256
i++;
12571257
uint64_t mem_reads_size = chunk[i];
1258-
printf("\t\tmem_reads_size=%ld:\n", mem_reads_size);
1258+
printf("\t\tmem_reads_size=%ld\n", mem_reads_size);
12591259
i++;
12601260
if (mem_reads_size > 10000000)
12611261
{
@@ -1266,7 +1266,7 @@ void log_trace(void)
12661266
{
12671267
for (uint64_t m=0; m<mem_reads_size; m++)
12681268
{
1269-
printf("\t\tchunk[%ld].mem_reads[%ld]=%08lx:\n", c, m, chunk[i]);
1269+
printf("\t\tchunk[%ld].mem_reads[%ld]=%08lx\n", c, m, chunk[i]);
12701270
i++;
12711271
}
12721272
}

emulator/src/emu.rs

+83-4
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ impl<'a> Emu<'a> {
11841184
callback: Option<impl Fn(EmuTrace)>,
11851185
) {
11861186
// Context, where the state of the execution is stored and modified at every execution step
1187-
self.ctx = self.create_emu_context(inputs);
1187+
self.ctx = self.create_emu_context(inputs.clone());
11881188

11891189
// Check that callback is provided if trace_steps is specified
11901190
if options.trace_steps.is_some() {
@@ -1213,6 +1213,35 @@ impl<'a> Emu<'a> {
12131213
if options.is_fast() {
12141214
return self.run_fast(options);
12151215
}
1216+
if options.generate_minimal_traces {
1217+
let par_emu_options =
1218+
ParEmuOptions { num_steps: 1024 * 1024, num_threads: 1, thread_id: 0 };
1219+
let minimal_trace = self.run_gen_trace(inputs, options, &par_emu_options);
1220+
1221+
for (c, chunk) in minimal_trace.iter().enumerate() {
1222+
println!("Chunk {}:", c);
1223+
println!("\tStart state:");
1224+
println!("\t\tpc=0x{:x}", chunk.start_state.pc);
1225+
println!("\t\tsp=0x{:x}", chunk.start_state.sp);
1226+
println!("\t\tc=0x{:x}", chunk.start_state.c);
1227+
println!("\t\tstep={}", chunk.start_state.step);
1228+
for i in 1..32 {
1229+
// TODO: 34
1230+
println!("\t\tregister[{}]=0x{:x}", i, chunk.start_state.regs[i]);
1231+
}
1232+
println!("\tLast state:");
1233+
println!("\t\tc=0x{:x}", chunk.last_c);
1234+
println!("\tEnd:");
1235+
println!("\t\tend={}", if chunk.end { 1 } else { 0 });
1236+
println!("\tSteps:");
1237+
println!("\t\tsteps={}", chunk.steps);
1238+
println!("\t\tmem_reads_size={}", chunk.mem_reads.len());
1239+
for i in 0..chunk.mem_reads.len() {
1240+
println!("\t\tchunk[{}].mem_reads[{}]={:08x}", c, i, chunk.mem_reads[i]);
1241+
}
1242+
}
1243+
return;
1244+
}
12161245
//println!("Emu::run() full-equipe");
12171246

12181247
// Store the stats option into the emulator context
@@ -1291,7 +1320,7 @@ impl<'a> Emu<'a> {
12911320
}
12921321

12931322
/// Run the whole program
1294-
pub fn par_run<F: PrimeField>(
1323+
pub fn par_run(
12951324
&mut self,
12961325
inputs: Vec<u8>,
12971326
options: &EmuOptions,
@@ -1335,7 +1364,8 @@ impl<'a> Emu<'a> {
13351364
end: false,
13361365
});
13371366
}
1338-
self.par_step_my_block::<F>(emu_traces.last_mut().unwrap());
1367+
1368+
self.par_step_my_block(emu_traces.last_mut().unwrap());
13391369

13401370
if self.ctx.inst_ctx.step >= options.max_steps {
13411371
panic!("Emu::par_run() reached max_steps");
@@ -1346,6 +1376,55 @@ impl<'a> Emu<'a> {
13461376
emu_traces
13471377
}
13481378

1379+
/// Run the whole program
1380+
pub fn run_gen_trace(
1381+
&mut self,
1382+
inputs: Vec<u8>,
1383+
options: &EmuOptions,
1384+
par_options: &ParEmuOptions,
1385+
) -> Vec<EmuTrace> {
1386+
// Context, where the state of the execution is stored and modified at every execution step
1387+
self.ctx = self.create_emu_context(inputs);
1388+
1389+
// Init pc to the rom entry address
1390+
self.ctx.trace.start_state.pc = ROM_ENTRY;
1391+
1392+
// Store the stats option into the emulator context
1393+
self.ctx.do_stats = options.stats;
1394+
1395+
// Set emulation mode
1396+
self.ctx.inst_ctx.emulation_mode = EmulationMode::GenerateMemReads;
1397+
1398+
let mut emu_traces = Vec::new();
1399+
1400+
while !self.ctx.inst_ctx.end {
1401+
// Check if is the first step of a new block
1402+
if self.ctx.inst_ctx.step % par_options.num_steps as u64 == 0 {
1403+
emu_traces.push(EmuTrace {
1404+
start_state: EmuTraceStart {
1405+
pc: self.ctx.inst_ctx.pc,
1406+
sp: self.ctx.inst_ctx.sp,
1407+
c: self.ctx.inst_ctx.c,
1408+
step: self.ctx.inst_ctx.step,
1409+
regs: self.ctx.inst_ctx.regs,
1410+
},
1411+
last_c: 0,
1412+
steps: 0,
1413+
mem_reads: Vec::with_capacity(par_options.num_steps),
1414+
end: false,
1415+
});
1416+
}
1417+
1418+
self.par_step_my_block(emu_traces.last_mut().unwrap());
1419+
1420+
if self.ctx.inst_ctx.step >= options.max_steps {
1421+
panic!("Emu::par_run() reached max_steps");
1422+
}
1423+
}
1424+
1425+
emu_traces
1426+
}
1427+
13491428
/// Performs one single step of the emulation
13501429
#[inline(always)]
13511430
#[allow(unused_variables)]
@@ -1454,7 +1533,7 @@ impl<'a> Emu<'a> {
14541533

14551534
/// Performs one single step of the emulation
14561535
#[inline(always)]
1457-
pub fn par_step_my_block<F: PrimeField>(&mut self, emu_full_trace_vec: &mut EmuTrace) {
1536+
pub fn par_step_my_block(&mut self, emu_full_trace_vec: &mut EmuTrace) {
14581537
let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc);
14591538
// Build the 'a' register value based on the source specified by the current instruction
14601539
self.source_a_mem_reads_generate(instruction, &mut emu_full_trace_vec.mem_reads);

emulator/src/emu_options.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ pub struct EmuOptions {
6161
/// Generates statistics about opcodes and memory usage. Enabled with `-x`.
6262
#[clap(short = 'x', long, value_name = "STATS", default_value = "false")]
6363
pub stats: bool,
64+
/// Generates minimal traces. Enabled with `-g`.
65+
#[clap(short = 'g', long, value_name = "MINIMAL_TRACES", default_value = "false")]
66+
pub generate_minimal_traces: bool,
6467
}
6568

6669
impl Default for EmuOptions {
@@ -81,6 +84,7 @@ impl Default for EmuOptions {
8184
log_metrics: false,
8285
tracerv: false,
8386
stats: false,
87+
generate_minimal_traces: false,
8488
}
8589
}
8690
}
@@ -101,7 +105,8 @@ impl fmt::Display for EmuOptions {
101105
writeln!(f, "METRICS: {:?}", self.log_metrics)?;
102106
writeln!(f, "STATS: {:?}", self.stats)?;
103107
writeln!(f, "TRACERV: {:?}", self.tracerv)?;
104-
writeln!(f, "LOG_STEP: {:?}", self.log_step)
108+
writeln!(f, "LOG_STEP: {:?}", self.log_step)?;
109+
writeln!(f, "MINIMAL_TRACES: {:?}", self.generate_minimal_traces)
105110
}
106111
}
107112

@@ -115,5 +120,6 @@ impl EmuOptions {
115120
&& !self.verbose
116121
&& !self.tracerv
117122
&& !self.stats
123+
&& !self.generate_minimal_traces
118124
}
119125
}

emulator/src/emulator.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl ZiskEmulator {
177177
/// First phase of the witness computation
178178
/// 8 threads in waterfall (# threads to be re-calibrated after memory reads refactor)
179179
/// Must be fast
180-
pub fn compute_minimal_traces<F: PrimeField>(
180+
pub fn compute_minimal_traces(
181181
rom: &ZiskRom,
182182
inputs: &[u8],
183183
options: &EmuOptions,
@@ -191,7 +191,7 @@ impl ZiskEmulator {
191191

192192
// Run the emulation
193193
let mut emu = Emu::new(rom);
194-
let result = emu.par_run::<F>(inputs.to_owned(), options, &par_emu_options);
194+
let result = emu.par_run(inputs.to_owned(), options, &par_emu_options);
195195

196196
if !emu.terminated() {
197197
panic!("Emulation did not complete");

executor/src/executor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<F: PrimeField64> ZiskExecutor<F> {
197197
..EmuOptions::default()
198198
};
199199

200-
let min_traces = ZiskEmulator::compute_minimal_traces::<F>(
200+
let min_traces = ZiskEmulator::compute_minimal_traces(
201201
&self.zisk_rom,
202202
&input_data,
203203
&emu_options,

0 commit comments

Comments
 (0)