@@ -135,28 +135,63 @@ def sym_block1 (blockSize stepsLeft : Nat) : SymM Unit := do
135
135
traceHeartbeats
136
136
137
137
syntax sym_block_size := "(" "block_size" " := " num ")"
138
+ syntax sym_block_sizes := "(" "block_sizes" " := " "[" num,* "]" ")"
139
+
140
+ /--
141
+ Get the first `n` elements of the list `xs`, where `acc` is the accumulator.
142
+
143
+ (FIXME) Implicit assumption: `xs` has at least one assumption.
144
+ -/
145
+ def first_n (n : Nat) (xs acc : List Nat) : List Nat :=
146
+ match n with
147
+ | 0 => acc.reverse
148
+ | n' + 1 => first_n n' xs.tail (List.headD xs 0 :: acc)
149
+
150
+ /-- info: 5 -/
151
+ #guard_msgs in
152
+ #eval (first_n 1 [5 , 2 , 2 , 1 ] []).foldl Nat.add 0
138
153
139
154
open Elab.Term (elabTerm) in
140
- elab "sym_block" n:num block_size:(sym_block_size)? s:(sym_at)? : tactic => do
155
+ elab "sym_block" n:num
156
+ -- block_size:(sym_block_size)?
157
+ block_sizes:(sym_block_sizes)?
158
+ s:(sym_at)? : tactic => do
141
159
traceHeartbeats "initial heartbeats"
142
160
143
161
let s ← s.mapM fun
144
162
| `(sym_at|at $s:ident) => pure s.getId
145
163
| _ => Lean.Elab.throwUnsupportedSyntax
146
- let block_size ← block_size.mapM (fun
147
- | `(sym_block_size|(block_size := $val)) => pure val.getNat
148
- | _ => -- If no block size is specified, we step one instruction at a time.
149
- pure 1 )
150
- let block_size := block_size.get!
164
+ let block_sizes ← block_sizes.mapM (fun
165
+ | `(sym_block_sizes|(block_sizes := [$elems,*])) => do
166
+ let size_exprs ← elems.getElems.mapM (fun elem => do
167
+ let size := elem.getNat
168
+ return (mkNatLit size))
169
+ let size_terms ← size_exprs.mapM (fun e => do
170
+ let some val ← Lean.Meta.getNatValue? e | throwError ""
171
+ return val)
172
+ dbg_trace s! "size_terms: { size_terms} "
173
+ pure size_terms.toList
174
+ | _ =>
175
+ -- (FIXME)
176
+ -- If no block size is specified, we step one instruction at a time.
177
+ pure [1 ])
178
+ let block_sizes := block_sizes.get!
179
+ trace[Tactic.sym.info] "block_sizes: {block_sizes}"
180
+
181
+ -- let block_size ← block_size.mapM (fun
182
+ -- | `(sym_block_size|(block_size := $val)) => pure val.getNat
183
+ -- | _ => -- If no block size is specified, we step one instruction at a time.
184
+ -- pure 1)
185
+ -- let block_size := block_size.get!
151
186
152
187
let c ← SymContext.fromMainContext s
153
188
-- TODO: Is this `get!` safe?
154
- let total_steps := c.runSteps?.get!
189
+ -- let total_steps := c.runSteps?.get!
155
190
-- The number of instructions, not blocks, the user asked to simulate.
156
191
let sim_steps := n.getNat
157
192
-- We compute the number of blocks to be simulated using a ceiling divide.
158
193
-- Note that the last block can be < `block_size`.
159
- let num_blocks := (sim_steps + block_size - 1 ) / block_size
194
+ -- let num_blocks := (sim_steps + block_size - 1) / block_size
160
195
161
196
SymM.run' c <| withMainContext' <| do
162
197
-- Check pre-conditions
@@ -166,10 +201,15 @@ elab "sym_block" n:num block_size:(sym_block_size)? s:(sym_at)? : tactic => do
166
201
167
202
withMainContext' <| do
168
203
-- The main loop
169
- for i in List.range num_blocks do
170
- let block_size' := min (sim_steps - (i * block_size)) block_size
171
- let steps_left := (total_steps - (i * block_size) - block_size')
172
- sym_block1 block_size' steps_left
204
+ -- for i in List.range num_blocks do
205
+ -- let block_size' := min (sim_steps - (i * block_size)) block_size
206
+ -- let steps_left := (total_steps - (i * block_size) - block_size')
207
+ -- sym_block1 block_size' steps_left
208
+ let mut ctr := 0
209
+ for bsize in block_sizes do
210
+ ctr := ctr + 1
211
+ let steps_left := sim_steps - ((first_n ctr block_sizes []).foldl Nat.add 0 )
212
+ sym_block1 bsize steps_left
173
213
174
214
traceHeartbeats "symbolic simulation total"
175
215
withCurrHeartbeats <|
0 commit comments