aboutsummaryrefslogtreecommitdiffstats
path: root/src/hls/DVeriloggenproof.v
blob: 197d9a6f6807493b0d64ee1c7379500acb83319d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
(*
 * Vericert: Verified high-level synthesis.
 * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *)

From compcert Require Import Smallstep Linking Integers Globalenvs.
From vericert Require HTL.
From vericert Require Import Vericertlib DVeriloggen Verilog ValueInt AssocMap.
Require Import Lia.

Local Open Scope assocmap.

Definition match_prog (prog : DHTL.program) (tprog : Verilog.program) :=
  match_program (fun cu f tf => tf = transl_fundef f) eq prog tprog.

Lemma transf_program_match:
  forall prog, match_prog prog (transl_program prog).
Proof.
  intros. eapply match_transform_program_contextual. auto.
Qed.

Inductive match_stacks : list DHTL.stackframe -> list stackframe -> Prop :=
| match_stack :
    forall res m pc reg_assoc arr_assoc hstk vstk,
      match_stacks hstk vstk ->
      match_stacks (DHTL.Stackframe res m pc reg_assoc arr_assoc :: hstk)
                   (Stackframe res (transl_module m) pc
                                       reg_assoc arr_assoc :: vstk)
| match_stack_nil : match_stacks nil nil.

Inductive match_states : DHTL.state -> state -> Prop :=
| match_state :
    forall m st reg_assoc arr_assoc hstk vstk,
      match_stacks hstk vstk ->
      match_states (DHTL.State hstk m st reg_assoc arr_assoc)
                   (State vstk (transl_module m) st reg_assoc arr_assoc)
| match_returnstate :
    forall v hstk vstk,
      match_stacks hstk vstk ->
      match_states (DHTL.Returnstate hstk v) (Returnstate vstk v)
| match_initial_call :
    forall m,
      match_states (DHTL.Callstate nil m nil) (Callstate nil (transl_module m) nil).

Lemma Vlit_inj :
  forall a b, Vlit a = Vlit b -> a = b.
Proof. inversion 1. trivial. Qed.

Lemma posToValue_inj :
  forall a b,
    0 <= Z.pos a <= Int.max_unsigned ->
    0 <= Z.pos b <= Int.max_unsigned ->
    posToValue a = posToValue b ->
    a = b.
Proof.
  intros. rewrite <- Pos2Z.id at 1. rewrite <- Pos2Z.id.
  rewrite <- Int.unsigned_repr at 1; try assumption.
  symmetry.
  rewrite <- Int.unsigned_repr at 1; try assumption.
  unfold posToValue in *. rewrite H1; auto.
Qed.

Lemma valueToPos_inj :
  forall a b,
    0 < Int.unsigned a ->
    0 < Int.unsigned b ->
    valueToPos a = valueToPos b ->
    a = b.
Proof.
  intros. unfold valueToPos in *.
  rewrite <- Int.repr_unsigned at 1.
  rewrite <- Int.repr_unsigned.
  apply Pos2Z.inj_iff in H1.
  rewrite Z2Pos.id in H1; auto.
  rewrite Z2Pos.id in H1; auto.
  rewrite H1. auto.
Qed.

Lemma unsigned_posToValue_le :
  forall p,
    Z.pos p <= Int.max_unsigned ->
    0 < Int.unsigned (posToValue p).
Proof.
  intros. unfold posToValue. rewrite Int.unsigned_repr; lia.
Qed.

Lemma transl_list_fun_fst :
  forall p1 p2 a b,
    0 <= Z.pos p1 <= Int.max_unsigned ->
    0 <= Z.pos p2 <= Int.max_unsigned ->
    transl_list_fun (p1, a) = transl_list_fun (p2, b) ->
    (p1, a) = (p2, b).
Proof.
  intros. unfold transl_list_fun in H1. apply pair_equal_spec in H1.
  destruct H1. rewrite H2. apply Vlit_inj in H1.
  apply posToValue_inj in H1; try assumption.
  rewrite H1; auto.
Qed.

Lemma Zle_relax :
  forall p q r,
  p < q <= r ->
  p <= q <= r.
Proof. lia. Qed.
#[local] Hint Resolve Zle_relax : verilogproof.

Lemma transl_in :
  forall l p,
  0 <= Z.pos p <= Int.max_unsigned ->
  (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) ->
  In (Vlit (posToValue p)) (map fst (map transl_list_fun l)) ->
  In p (map fst l).
Proof.
  induction l.
  - simplify. auto.
  - intros. destruct a. simplify. destruct (peq p0 p); auto.
    right. inv H1. apply Vlit_inj in H. apply posToValue_inj in H; auto. contradiction.
    auto with verilogproof.
    apply IHl; auto.
Qed.

Lemma transl_notin :
  forall l p,
    0 <= Z.pos p <= Int.max_unsigned ->
    (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) ->
    ~ In p (List.map fst l) -> ~ In (Vlit (posToValue p)) (List.map fst (transl_list l)).
Proof.
  induction l; auto. intros. destruct a. unfold not in *. intros.
  simplify.
  destruct (peq p0 p). apply H1. auto. apply H1.
  unfold transl_list in *. inv H2. apply Vlit_inj in H. apply posToValue_inj in H.
  contradiction.
  auto with verilogproof. auto.
  right. apply transl_in; auto.
Qed.

Lemma transl_norepet :
  forall l,
    (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) ->
    list_norepet (List.map fst l) -> list_norepet (List.map fst (transl_list l)).
Proof.
  induction l.
  - intros. simpl. apply list_norepet_nil.
  - destruct a. intros. simpl. apply list_norepet_cons.
    inv H0. apply transl_notin. apply Zle_relax. apply H. simplify; auto.
    intros. apply H. destruct (peq p0 p); subst; simplify; auto.
    assumption. apply IHl. intros. apply H. destruct (peq p0 p); subst; simplify; auto.
    simplify. inv H0. assumption.
Qed.

Lemma transl_list_correct :
  forall l v ev f asr asa asrn asan asr' asa' asrn' asan',
    (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) ->
    list_norepet (List.map fst l) ->
    asr!ev = Some v ->
    (forall p s,
        In (p, s) l ->
        v = posToValue p ->
        stmnt_runp f
                   {| assoc_blocking := asr; assoc_nonblocking := asrn |}
                   {| assoc_blocking := asa; assoc_nonblocking := asan |}
                   s
                   {| assoc_blocking := asr'; assoc_nonblocking := asrn' |}
                   {| assoc_blocking := asa'; assoc_nonblocking := asan' |} ->
        stmnt_runp f
                   {| assoc_blocking := asr; assoc_nonblocking := asrn |}
                   {| assoc_blocking := asa; assoc_nonblocking := asan |}
                   (Vcase (Vvar ev) (list_to_stmnt (transl_list l)) (Some Vskip))
                   {| assoc_blocking := asr'; assoc_nonblocking := asrn' |}
                   {| assoc_blocking := asa'; assoc_nonblocking := asan' |}).
Proof.
  induction l as [| a l IHl].
  - contradiction.
  - intros v ev f asr asa asrn asan asr' asa' asrn' asan' BOUND NOREP ASSOC p s IN EQ SRUN.
    destruct a as [p' s']. simplify.
    destruct (peq p p'); subst. eapply stmnt_runp_Vcase_match.
    constructor. simplify. unfold AssocMap.find_assocmap, AssocMapExt.get_default.
    rewrite ASSOC. trivial. constructor. auto.
    inversion IN as [INV | INV]. inversion INV as [INV2]; subst. assumption.
    inv NOREP. eapply in_map with (f := fst) in INV. contradiction.

    eapply stmnt_runp_Vcase_nomatch. constructor. simplify.
    unfold AssocMap.find_assocmap, AssocMapExt.get_default. rewrite ASSOC.
    trivial. constructor. unfold not. intros. apply n. apply posToValue_inj.
    apply Zle_relax. apply BOUND. right. inv IN. inv H0; contradiction.
    eapply in_map with (f := fst) in H0. auto.
    apply Zle_relax. apply BOUND; auto. auto.

    eapply IHl. auto. inv NOREP. auto. eassumption. inv IN. inv H. contradiction. apply H.
    trivial. assumption.
Qed.
#[local] Hint Resolve transl_list_correct : verilogproof.

Lemma pc_wf :
  forall A m p v,
  (forall p0, In p0 (List.map fst (@AssocMap.elements A m)) -> 0 < Z.pos p0 <= Int.max_unsigned) ->
  m!p = Some v ->
  0 <= Z.pos p <= Int.max_unsigned.
Proof.
  intros A m p v LT S. apply Zle_relax. apply LT.
  apply AssocMap.elements_correct in S. remember (p, v) as x.
  exploit in_map. apply S. instantiate (1 := fst). subst. simplify. auto.
Qed.

Lemma mis_stepp_decl :
  forall l asr asa f,
    mis_stepp f asr asa (map Vdeclaration l) asr asa.
Proof.
  induction l.
  - intros. constructor.
  - intros. simplify. econstructor. constructor. auto.
Qed.
#[local] Hint Resolve mis_stepp_decl : verilogproof.

Lemma mis_stepp_negedge_decl :
  forall l asr asa f,
    mis_stepp_negedge f asr asa (map Vdeclaration l) asr asa.
Proof.
  induction l.
  - intros. constructor.
  - intros. simplify. econstructor. constructor. auto.
Qed.
#[local] Hint Resolve mis_stepp_negedge_decl : verilogproof.

Lemma mod_entrypoint_equiv m : mod_entrypoint (transl_module m) = DHTL.mod_entrypoint m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_st_equiv m : mod_st (transl_module m) = DHTL.mod_st m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_stk_equiv m : mod_stk (transl_module m) = DHTL.mod_stk m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_stk_len_equiv m : mod_stk_len (transl_module m) = DHTL.mod_stk_len m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_finish_equiv m : mod_finish (transl_module m) = DHTL.mod_finish m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_reset_equiv m : mod_reset (transl_module m) = DHTL.mod_reset m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_clk_equiv m : mod_clk (transl_module m) = DHTL.mod_clk m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_return_equiv m : mod_return (transl_module m) = DHTL.mod_return m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma mod_params_equiv m : mod_args (transl_module m) = DHTL.mod_params m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Lemma empty_stack_equiv m : empty_stack (transl_module m) = DHTL.empty_stack m.
Proof. unfold transl_module; intros; destruct (DHTL.mod_ram m) eqn:?; crush. Qed.

Ltac rewrite_eq := rewrite mod_return_equiv
                   || rewrite mod_clk_equiv
                   || rewrite mod_reset_equiv
                   || rewrite mod_finish_equiv
                   || rewrite mod_stk_len_equiv
                   || rewrite mod_stk_equiv
                   || rewrite mod_st_equiv
                   || rewrite mod_entrypoint_equiv
                   || rewrite mod_params_equiv
                   || rewrite empty_stack_equiv.

Lemma find_assocmap_get r i v : r ! i = Some v -> r # i = v.
Proof.
  intros. unfold find_assocmap, AssocMapExt.get_default. rewrite H. auto.
Qed.

Lemma ram_exec_match :
  forall f asr asa asr' asa' r clk,
    DHTL.exec_ram asr asa (Some r) asr' asa' ->
    mi_stepp_negedge f asr asa (inst_ram clk r) asr' asa'.
Proof.
  inversion 1; subst; simplify.
  { unfold inst_ram. econstructor.
    eapply stmnt_runp_Vcond_false.
    econstructor. econstructor. econstructor. auto.
    econstructor. auto.
    simplify.
    unfold boolToValue, natToValue, valueToBool.
    rewrite Int.eq_sym. rewrite H3. simplify.
    auto. constructor. }
  { unfold inst_ram. econstructor. econstructor. econstructor.
    econstructor. econstructor. auto.
    econstructor. auto.
    simplify.
    unfold boolToValue, natToValue, valueToBool.
    pose proof H4 as X. apply find_assocmap_get in X.
    rewrite X. rewrite Int.eq_sym. rewrite H1. auto.
    econstructor. econstructor. econstructor. econstructor.
    pose proof H5 as X. apply find_assocmap_get in X.
    rewrite X.
    unfold valueToBool. unfold ZToValue in *.
    unfold Int.eq in H2.
    unfold uvalueToZ.
    assert (Int.unsigned wr_en =? 0 = false).
    apply Z.eqb_neq. rewrite Int.unsigned_repr in H2 by (simplify; lia).
    destruct (zeq (Int.unsigned wr_en) 0); crush.
    rewrite H0. auto.
    apply stmnt_runp_Vnonblock_arr. econstructor. econstructor. auto.
    econstructor. econstructor.
    apply find_assocmap_get in H9. rewrite H9.
    apply find_assocmap_get in H6. rewrite H6.
    repeat econstructor. apply find_assocmap_get; auto.
  }
  { econstructor. econstructor. econstructor. econstructor. auto.
    econstructor. auto.
    econstructor.
    unfold boolToValue, natToValue, valueToBool.
    apply find_assocmap_get in H3. rewrite H3.
    rewrite Int.eq_sym. rewrite H1. auto.
    econstructor.
    eapply stmnt_runp_Vcond_false. econstructor. auto.
    simplify. apply find_assocmap_get in H4. rewrite H4.
    auto.
    repeat (econstructor; auto). apply find_assocmap_get in H5.
    rewrite H5. eassumption.
    repeat econstructor. simplify. apply find_assocmap_get; auto.
  }
Qed.


Section CORRECTNESS.

  Variable prog: DHTL.program.
  Variable tprog: program.

  Hypothesis TRANSL : match_prog prog tprog.

  Let ge : DHTL.genv := Globalenvs.Genv.globalenv prog.
  Let tge : genv := Globalenvs.Genv.globalenv tprog.

  Lemma symbols_preserved:
    forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
  Proof. intros. eapply (Genv.find_symbol_match TRANSL). Qed.
  #[local] Hint Resolve symbols_preserved : verilogproof.

  Lemma function_ptr_translated:
    forall (b: Values.block) (f: DHTL.fundef),
      Genv.find_funct_ptr ge b = Some f ->
      exists tf,
        Genv.find_funct_ptr tge b = Some tf /\ transl_fundef f = tf.
  Proof.
    intros. exploit (Genv.find_funct_ptr_match TRANSL); eauto.
    intros (cu & tf & P & Q & R); exists tf; auto.
  Qed.
  #[local] Hint Resolve function_ptr_translated : verilogproof.

  Lemma functions_translated:
    forall (v: Values.val) (f: DHTL.fundef),
      Genv.find_funct ge v = Some f ->
      exists tf,
        Genv.find_funct tge v = Some tf /\ transl_fundef f = tf.
  Proof.
    intros. exploit (Genv.find_funct_match TRANSL); eauto.
    intros (cu & tf & P & Q & R); exists tf; auto.
  Qed.
  #[local] Hint Resolve functions_translated : verilogproof.

  Lemma senv_preserved:
    Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge).
  Proof.
    intros. eapply (Genv.senv_match TRANSL).
  Qed.
  #[local] Hint Resolve senv_preserved : verilogproof.

  Ltac unfold_replace :=
    match goal with
    | H: DHTL.mod_ram _ = _ |- context[transl_module] =>
      unfold transl_module; rewrite H
    end.

  Theorem transl_step_correct :
    forall (S1 : DHTL.state) t S2,
      DHTL.step ge S1 t S2 ->
      forall (R1 : state),
        match_states S1 R1 ->
        exists R2, Smallstep.plus step tge R1 t R2 /\ match_states S2 R2.
  Proof.
    induction 1; intros R1 MSTATE; inv MSTATE; destruct (DHTL.mod_ram m) eqn:?.
    - econstructor; split. apply Smallstep.plus_one. econstructor.
      unfold_replace. assumption. unfold_replace. assumption.
      unfold_replace. eassumption. apply valueToPos_posToValue.
      split. lia.
  (*     eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*     split. lia. apply HP. eassumption. eassumption. *)
  (*     unfold_replace. *)
  (*     econstructor. econstructor. eapply stmnt_runp_Vcond_false. econstructor. econstructor. *)
  (*     simpl. unfold find_assocmap. unfold AssocMapExt.get_default. *)
  (*     rewrite H. trivial. *)

  (*     econstructor. simpl. auto. auto. *)

  (*     eapply transl_list_correct. *)
  (*     intros. split. lia. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. auto. *)
  (*     apply Maps.PTree.elements_keys_norepet. eassumption. *)
  (*     2: { apply valueToPos_inj. apply unsigned_posToValue_le. *)
  (*          eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. *)
  (*          apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. *)
  (*          destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. trivial. *)
  (*     } *)
  (*     apply Maps.PTree.elements_correct. eassumption. eassumption. *)

  (*     econstructor. econstructor. *)

  (*     eapply transl_list_correct. *)
  (*     intros. split. lia. pose proof (DHTL.mod_wf m) as HP. destruct HP as [_ HP]. *)
  (*     auto. apply Maps.PTree.elements_keys_norepet. eassumption. *)
  (*     2: { apply valueToPos_inj. apply unsigned_posToValue_le. *)
  (*          eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. *)
  (*          apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. *)
  (*          destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. trivial. *)
  (*     } *)
  (*     apply Maps.PTree.elements_correct. eassumption. eassumption. *)
  (*     econstructor. econstructor. *)
  (*     apply mis_stepp_decl. simplify. unfold_replace. simplify. *)
  (*     econstructor. econstructor. econstructor. econstructor. *)
  (*     econstructor. *)
  (*     apply ram_exec_match. eauto. *)
  (*     apply mis_stepp_negedge_decl. simplify. auto. auto. *)
  (*     rewrite_eq. eauto. auto. *)
  (*     rewrite valueToPos_posToValue. econstructor. auto. *)
  (*     simplify; lia. *)
  (*   - inv H7. econstructor; split. apply Smallstep.plus_one. econstructor. *)
  (*     unfold_replace. assumption. unfold_replace. assumption. *)
  (*     unfold_replace. eassumption. apply valueToPos_posToValue. *)
  (*     split. lia. *)
  (*     eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*     split. lia. apply HP. eassumption. eassumption. *)
  (*     unfold_replace. *)
  (*     econstructor. econstructor. eapply stmnt_runp_Vcond_false. econstructor. econstructor. *)
  (*     simpl. unfold find_assocmap. unfold AssocMapExt.get_default. *)
  (*     rewrite H. trivial. *)

  (*     econstructor. simpl. auto. auto. *)

  (*     eapply transl_list_correct. *)
  (*     intros. split. lia. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. auto. *)
  (*     apply Maps.PTree.elements_keys_norepet. eassumption. *)
  (*     2: { apply valueToPos_inj. apply unsigned_posToValue_le. *)
  (*          eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. *)
  (*          apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. *)
  (*          destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. trivial. *)
  (*     } *)
  (*     apply Maps.PTree.elements_correct. eassumption. eassumption. *)

  (*     econstructor. econstructor. *)

  (*     eapply transl_list_correct. *)
  (*     intros. split. lia. pose proof (DHTL.mod_wf m) as HP. *)
  (*     destruct HP as [_ HP]; auto. *)
  (*     apply Maps.PTree.elements_keys_norepet. eassumption. *)
  (*     2: { apply valueToPos_inj. apply unsigned_posToValue_le. *)
  (*          eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. *)
  (*          apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (DHTL.mod_wf m) as HP. *)
  (*          destruct HP as [HP _]. *)
  (*          split. lia. apply HP. eassumption. eassumption. trivial. *)
  (*     } *)
  (*     apply Maps.PTree.elements_correct. eassumption. eassumption. *)

  (*     apply mis_stepp_decl. simplify. *)
  (*     unfold_replace. *)
  (*     repeat econstructor. apply mis_stepp_negedge_decl. trivial. trivial. *)
  (*     simpl. unfold_replace. eassumption. auto. simplify. *)
  (*     rewrite valueToPos_posToValue. constructor; eassumption. simplify; lia. *)
  (*   - econstructor; split. apply Smallstep.plus_one. apply step_finish. *)
  (*     rewrite_eq. assumption. *)
  (*     rewrite_eq. eassumption. *)
  (*     econstructor; auto. *)
  (*   - econstructor; split. apply Smallstep.plus_one. apply step_finish. *)
  (*     unfold transl_module. rewrite Heqo. simplify. *)
  (*     assumption. unfold_replace. eassumption. *)
  (*     constructor; assumption. *)
  (*   - econstructor; split. apply Smallstep.plus_one. constructor. *)
  (*     repeat rewrite_eq. constructor. constructor. *)
  (*   - econstructor; split. apply Smallstep.plus_one. constructor. *)
  (*     repeat rewrite_eq. constructor. constructor. *)
  (*   - inv H3. econstructor; split. apply Smallstep.plus_one. constructor. trivial. *)
  (*     repeat rewrite_eq. apply match_state. assumption. *)
  (*   - inv H3. econstructor; split. apply Smallstep.plus_one. constructor. trivial. *)
  (*     repeat rewrite_eq. apply match_state. assumption. *)
  (* Qed. *) Admitted. (* This translation pass is only used for testing. *)
  #[local] Hint Resolve transl_step_correct : verilogproof.

  Lemma transl_initial_states :
    forall s1 : Smallstep.state (DHTL.semantics prog),
      Smallstep.initial_state (DHTL.semantics prog) s1 ->
      exists s2 : Smallstep.state (Verilog.semantics tprog),
        Smallstep.initial_state (Verilog.semantics tprog) s2 /\ match_states s1 s2.
  Proof.
    induction 1.
    econstructor; split. econstructor.
    apply (Genv.init_mem_transf TRANSL); eauto.
    rewrite symbols_preserved.
    replace (AST.prog_main tprog) with (AST.prog_main prog); eauto.
    symmetry; eapply Linking.match_program_main; eauto.
    exploit function_ptr_translated; eauto. intros [tf [A B]].
    inv B. eauto.
    constructor.
  Qed.
  #[local] Hint Resolve transl_initial_states : verilogproof.

  Lemma transl_final_states :
    forall (s1 : Smallstep.state (DHTL.semantics prog))
           (s2 : Smallstep.state (Verilog.semantics tprog))
           (r : Integers.Int.int),
      match_states s1 s2 ->
      Smallstep.final_state (DHTL.semantics prog) s1 r ->
      Smallstep.final_state (Verilog.semantics tprog) s2 r.
  Proof.
    intros. inv H0. inv H. inv H3. constructor. reflexivity.
  Qed.
  #[local] Hint Resolve transl_final_states : verilogproof.

  Theorem transf_program_correct:
    forward_simulation (DHTL.semantics prog) (Verilog.semantics tprog).
  Proof.
    eapply Smallstep.forward_simulation_plus; eauto with verilogproof.
    apply senv_preserved.
  Qed.

End CORRECTNESS.