aboutsummaryrefslogtreecommitdiffstats
path: root/src/verilog
diff options
context:
space:
mode:
Diffstat (limited to 'src/verilog')
-rw-r--r--src/verilog/AssocMap.v4
-rw-r--r--src/verilog/HTL.v34
-rw-r--r--src/verilog/PrintHTL.ml2
-rw-r--r--src/verilog/PrintVerilog.ml20
-rw-r--r--src/verilog/PrintVerilog.mli4
-rw-r--r--src/verilog/Value.v107
-rw-r--r--src/verilog/ValueInt.v162
-rw-r--r--src/verilog/Verilog.v345
8 files changed, 552 insertions, 126 deletions
diff --git a/src/verilog/AssocMap.v b/src/verilog/AssocMap.v
index 5d531d5..c5cfa3f 100644
--- a/src/verilog/AssocMap.v
+++ b/src/verilog/AssocMap.v
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
-From coqup Require Import Coquplib Value.
+From coqup Require Import Coquplib ValueInt.
From compcert Require Import Maps.
Definition reg := positive.
@@ -192,7 +192,7 @@ Import AssocMapExt.
Definition assocmap := AssocMap.t value.
Definition find_assocmap (n : nat) : reg -> assocmap -> value :=
- get_default value (ZToValue n 0).
+ get_default value (ZToValue 0).
Definition empty_assocmap : assocmap := AssocMap.empty value.
diff --git a/src/verilog/HTL.v b/src/verilog/HTL.v
index a3623f0..b3d1442 100644
--- a/src/verilog/HTL.v
+++ b/src/verilog/HTL.v
@@ -17,13 +17,11 @@
*)
From Coq Require Import FSets.FMapPositive.
-From coqup Require Import Coquplib Value AssocMap Array.
+From coqup Require Import Coquplib ValueInt AssocMap Array.
From coqup Require Verilog.
From compcert Require Events Globalenvs Smallstep Integers Values.
From compcert Require Import Maps.
-Import HexNotationValue.
-
(** The purpose of the hardware transfer language (HTL) is to create a more
hardware-like layout that is still similar to the register transfer language
(RTL) that it came from. The main change is that function calls become module
@@ -38,6 +36,11 @@ Definition node := positive.
Definition datapath := PTree.t Verilog.stmnt.
Definition controllogic := PTree.t Verilog.stmnt.
+Definition map_well_formed {A : Type} (m : PTree.t A) : Prop :=
+ forall p0 : positive,
+ In p0 (map fst (Maps.PTree.elements m)) ->
+ Z.pos p0 <= Integers.Int.max_unsigned.
+
Record module: Type :=
mkmodule {
mod_params : list reg;
@@ -54,6 +57,7 @@ Record module: Type :=
mod_clk : reg;
mod_scldecls : AssocMap.t (option Verilog.io * Verilog.scl_decl);
mod_arrdecls : AssocMap.t (option Verilog.io * Verilog.arr_decl);
+ mod_wf : (map_well_formed mod_controllogic /\ map_well_formed mod_datapath);
}.
Definition fundef := AST.fundef module.
@@ -99,14 +103,15 @@ Inductive state : Type :=
Inductive step : genv -> state -> Events.trace -> state -> Prop :=
| step_module :
- forall g m st sf ctrl data ist
+ forall g m st sf ctrl data
asr asa
basr1 basa1 nasr1 nasa1
basr2 basa2 nasr2 nasa2
asr' asa'
- f stval pstval,
- asr!(m.(mod_st)) = Some ist ->
- valueToPos ist = st ->
+ f pstval,
+ asr!(mod_reset m) = Some (ZToValue 0) ->
+ asr!(mod_finish m) = Some (ZToValue 0) ->
+ asr!(m.(mod_st)) = Some (posToValue st) ->
m.(mod_controllogic)!st = Some ctrl ->
m.(mod_datapath)!st = Some data ->
Verilog.stmnt_runp f
@@ -115,6 +120,7 @@ Inductive step : genv -> state -> Events.trace -> state -> Prop :=
ctrl
(Verilog.mkassociations basr1 nasr1)
(Verilog.mkassociations basa1 nasa1) ->
+ basr1!(m.(mod_st)) = Some (posToValue st) ->
Verilog.stmnt_runp f
(Verilog.mkassociations basr1 nasr1)
(Verilog.mkassociations basa1 nasa1)
@@ -123,26 +129,28 @@ Inductive step : genv -> state -> Events.trace -> state -> Prop :=
(Verilog.mkassociations basa2 nasa2) ->
asr' = Verilog.merge_regs nasr2 basr2 ->
asa' = Verilog.merge_arrs nasa2 basa2 ->
- asr'!(m.(mod_st)) = Some stval ->
- valueToPos stval = pstval ->
+ asr'!(m.(mod_st)) = Some (posToValue pstval) ->
+ Z.pos pstval <= Integers.Int.max_unsigned ->
step g (State sf m st asr asa) Events.E0 (State sf m pstval asr' asa')
| step_finish :
forall g m st asr asa retval sf,
- asr!(m.(mod_finish)) = Some (1'h"1") ->
+ asr!(m.(mod_finish)) = Some (ZToValue 1) ->
asr!(m.(mod_return)) = Some retval ->
step g (State sf m st asr asa) Events.E0 (Returnstate sf retval)
| step_call :
forall g m args res,
step g (Callstate res m args) Events.E0
(State res m m.(mod_entrypoint)
- (AssocMap.set (mod_st m) (posToValue 32 m.(mod_entrypoint))
- (init_regs args m.(mod_params)))
+ (AssocMap.set (mod_reset m) (ZToValue 0)
+ (AssocMap.set (mod_finish m) (ZToValue 0)
+ (AssocMap.set (mod_st m) (posToValue m.(mod_entrypoint))
+ (init_regs args m.(mod_params)))))
(empty_stack m))
| step_return :
forall g m asr asa i r sf pc mst,
mst = mod_st m ->
step g (Returnstate (Stackframe r m pc asr asa :: sf) i) Events.E0
- (State sf m pc ((asr # mst <- (posToValue 32 pc)) # r <- i) asa).
+ (State sf m pc ((asr # mst <- (posToValue pc)) # r <- i) asa).
Hint Constructors step : htl.
Inductive initial_state (p: program): state -> Prop :=
diff --git a/src/verilog/PrintHTL.ml b/src/verilog/PrintHTL.ml
index 0bdba51..36fdd3c 100644
--- a/src/verilog/PrintHTL.ml
+++ b/src/verilog/PrintHTL.ml
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
-open Value
+open ValueInt
open Datatypes
open Camlcoq
open AST
diff --git a/src/verilog/PrintVerilog.ml b/src/verilog/PrintVerilog.ml
index f8d597a..a172b3a 100644
--- a/src/verilog/PrintVerilog.ml
+++ b/src/verilog/PrintVerilog.ml
@@ -17,7 +17,7 @@
*)
open Verilog
-open Value
+open ValueInt
open Datatypes
open Camlcoq
@@ -70,16 +70,30 @@ let unop = function
let register a = sprintf "reg_%d" (P.to_int a)
-let literal l = sprintf "%d'd%d" (Nat.to_int l.vsize) (Z.to_int (uvalueToZ l))
+let literal l = sprintf "32'd%d" (Z.to_int (uvalueToZ l))
-let rec pprint_expr = function
+let literal_int i = sprintf "32'd%d" i
+
+let byte n s = sprintf "reg_%d[%d:%d]" (P.to_int s) (7 + n * 8) (n * 8)
+
+
+let rec pprint_expr =
+ let array_byte r i = function
+ | 0 -> concat [register r; "["; pprint_expr i; "]"]
+ | n -> concat [register r; "["; pprint_expr i; " + "; literal_int n; "][7:0]"]
+ in function
| Vlit l -> literal l
| Vvar s -> register s
+ | Vvarb0 s -> byte 0 s
+ | Vvarb1 s -> byte 1 s
+ | Vvarb2 s -> byte 2 s
+ | Vvarb3 s -> byte 3 s
| Vvari (s, i) -> concat [register s; "["; pprint_expr i; "]"]
| Vinputvar s -> register s
| Vunop (u, e) -> concat ["("; unop u; pprint_expr e; ")"]
| Vbinop (op, a, b) -> concat [pprint_binop (pprint_expr a) (pprint_expr b) op]
| Vternary (c, t, f) -> concat ["("; pprint_expr c; " ? "; pprint_expr t; " : "; pprint_expr f; ")"]
+ | Vload (s, i) -> concat ["{"; array_byte s i 3; ", "; array_byte s i 2; ", "; array_byte s i 1; ", "; array_byte s i 0; "}"]
let rec pprint_stmnt i =
let pprint_case (e, s) = concat [ indent (i + 1); pprint_expr e; ": begin\n"; pprint_stmnt (i + 2) s;
diff --git a/src/verilog/PrintVerilog.mli b/src/verilog/PrintVerilog.mli
index 62bf63f..5fd8fe9 100644
--- a/src/verilog/PrintVerilog.mli
+++ b/src/verilog/PrintVerilog.mli
@@ -18,8 +18,8 @@
val pprint_stmnt : int -> Verilog.stmnt -> string
-val print_value : out_channel -> Value.value -> unit
+val print_value : out_channel -> ValueInt.value -> unit
val print_program : bool -> out_channel -> Verilog.program -> unit
-val print_result : out_channel -> (BinNums.positive * Value.value) list -> unit
+val print_result : out_channel -> (BinNums.positive * ValueInt.value) list -> unit
diff --git a/src/verilog/Value.v b/src/verilog/Value.v
index 8ba5138..af2b822 100644
--- a/src/verilog/Value.v
+++ b/src/verilog/Value.v
@@ -21,6 +21,7 @@ From bbv Require Import Word.
From bbv Require HexNotation WordScope.
From Coq Require Import ZArith.ZArith FSets.FMapPositive Lia.
From compcert Require Import lib.Integers common.Values.
+From coqup Require Import Coquplib.
(* end hide *)
(** * Value
@@ -39,6 +40,8 @@ Record value : Type :=
vword: word vsize
}.
+Search N.of_nat.
+
(** ** Value conversions
Various conversions to different number types such as [N], [Z], [positive] and
@@ -85,9 +88,18 @@ Definition intToValue (i : Integers.int) : value :=
Definition valueToInt (i : value) : Integers.int :=
Int.repr (uvalueToZ i).
+Definition ptrToValue (i : Integers.ptrofs) : value :=
+ ZToValue Ptrofs.wordsize (Ptrofs.unsigned i).
+
+Definition valueToPtr (i : value) : Integers.ptrofs :=
+ Ptrofs.repr (uvalueToZ i).
+
Definition valToValue (v : Values.val) : option value :=
match v with
| Values.Vint i => Some (intToValue i)
+ | Values.Vptr b off => if Z.eqb (Z.modulo (uvalueToZ (ptrToValue off)) 4) 0%Z
+ then Some (ptrToValue off)
+ else None
| Values.Vundef => Some (ZToValue 32 0%Z)
| _ => None
end.
@@ -301,8 +313,8 @@ Inductive val_value_lessdef: val -> value -> Prop :=
val_value_lessdef (Vint i) v'
| val_value_lessdef_ptr:
forall b off v',
- off = Ptrofs.repr (valueToZ v') ->
- (Z.modulo (valueToZ v') 4) = 0%Z ->
+ off = valueToPtr v' ->
+ (Z.modulo (uvalueToZ v') 4) = 0%Z ->
val_value_lessdef (Vptr b off) v'
| lessdef_undef: forall v, val_value_lessdef Vundef v.
@@ -379,6 +391,41 @@ Proof.
apply Z.lt_le_pred in H. apply H.
Qed.
+Lemma valueToPtr_ptrToValue :
+ forall v,
+ valueToPtr (ptrToValue v) = v.
+Proof.
+ intros.
+ unfold valueToPtr, ptrToValue. rewrite uvalueToZ_ZToValue. auto using Ptrofs.repr_unsigned.
+ split. apply Ptrofs.unsigned_range_2.
+ assert ((Ptrofs.unsigned v <= Ptrofs.max_unsigned)%Z) by apply Ptrofs.unsigned_range_2.
+ apply Z.lt_le_pred in H. apply H.
+Qed.
+
+Lemma intToValue_valueToInt :
+ forall v,
+ vsize v = 32%nat ->
+ intToValue (valueToInt v) = v.
+Proof.
+ intros. unfold valueToInt, intToValue. rewrite Int.unsigned_repr_eq.
+ unfold ZToValue, uvalueToZ. unfold Int.modulus. unfold Int.wordsize. unfold Wordsize_32.wordsize.
+ pose proof (uwordToZ_bound (vword v)).
+ rewrite Z.mod_small. rewrite <- H. rewrite ZToWord_uwordToZ. destruct v; auto.
+ rewrite <- H. rewrite two_power_nat_equiv. apply H0.
+Qed.
+
+Lemma ptrToValue_valueToPtr :
+ forall v,
+ vsize v = 32%nat ->
+ ptrToValue (valueToPtr v) = v.
+Proof.
+ intros. unfold valueToPtr, ptrToValue. rewrite Ptrofs.unsigned_repr_eq.
+ unfold ZToValue, uvalueToZ. unfold Ptrofs.modulus. unfold Ptrofs.wordsize. unfold Wordsize_Ptrofs.wordsize.
+ pose proof (uwordToZ_bound (vword v)).
+ rewrite Z.mod_small. rewrite <- H. rewrite ZToWord_uwordToZ. destruct v; auto.
+ rewrite <- H. rewrite two_power_nat_equiv. apply H0.
+Qed.
+
Lemma valToValue_lessdef :
forall v v',
valToValue v = Some v' ->
@@ -388,6 +435,10 @@ Proof.
destruct v; try discriminate; constructor.
unfold valToValue in H. inversion H.
symmetry. apply valueToInt_intToValue.
+ inv H. destruct (uvalueToZ (ptrToValue i) mod 4 =? 0); try discriminate.
+ inv H1. symmetry. apply valueToPtr_ptrToValue.
+ inv H. destruct (uvalueToZ (ptrToValue i) mod 4 =? 0) eqn:?; try discriminate.
+ inv H1. apply Z.eqb_eq. apply Heqb0.
Qed.
Lemma boolToValue_ValueToBool :
@@ -415,6 +466,10 @@ Proof.
rewrite ZToWord_plus; auto.
Qed.
+Lemma ZToValue_eq :
+ forall w1,
+ (mkvalue 32 w1) = (ZToValue 32 (wordToZ w1)). Abort.
+
Lemma wordsize_32 :
Int.wordsize = 32%nat.
Proof. auto. Qed.
@@ -428,6 +483,28 @@ Proof.
rewrite Int.repr_unsigned. auto. rewrite wordsize_32. omega.
Qed.
+(*Lemma intadd_vplus2 :
+ forall v1 v2 EQ,
+ vsize v1 = 32%nat ->
+ Int.add (valueToInt v1) (valueToInt v2) = valueToInt (vplus v1 v2 EQ).
+Proof.
+ intros. unfold Int.add, valueToInt, intToValue. repeat (rewrite Int.unsigned_repr).
+ rewrite (@vadd_vplus v1 v2 EQ). trivial.
+ unfold uvalueToZ. Search word "bound". pose proof (@uwordToZ_bound (vsize v2) (vword v2)).
+ rewrite H in EQ. rewrite <- EQ in H0 at 3.*)
+ (*rewrite zadd_vplus3. trivia*)
+
+Lemma valadd_vplus :
+ forall v1 v2 v1' v2' v v' EQ,
+ val_value_lessdef v1 v1' ->
+ val_value_lessdef v2 v2' ->
+ Val.add v1 v2 = v ->
+ vplus v1' v2' EQ = v' ->
+ val_value_lessdef v v'.
+Proof.
+ intros. inv H; inv H0; constructor; simplify.
+ Abort.
+
Lemma zsub_vminus :
forall sz z1 z2,
(sz > 0)%nat ->
@@ -452,17 +529,25 @@ Proof.
unfold wordBin. repeat (rewrite wordToN_NToWord_2); auto.
Qed.
-(*Lemma ZToValue_valueToNat :
+Lemma ZToValue_valueToNat :
forall x sz,
- sz > 0 ->
- (x < 2^(Z.of_nat sz))%Z ->
+ (sz > 0)%nat ->
+ (0 <= x < 2^(Z.of_nat sz))%Z ->
valueToNat (ZToValue sz x) = Z.to_nat x.
Proof.
- destruct x; intros; unfold ZToValue, valueToNat; simpl.
+ destruct x; intros; unfold ZToValue, valueToNat; crush.
- rewrite wzero'_def. apply wordToNat_wzero.
- rewrite posToWord_nat. rewrite wordToNat_natToWord_2. trivial.
- unfold Z.of_nat in *. destruct sz eqn:?. omega. simpl in H0.
- rewrite <- Pos2Z.inj_pow_pos in H0. Search (Z.pos _ < Z.pos _)%Z.
- Search Pos.to_nat (_ < _). (* Pos2Nat.inj_lt *)
- Search "inj" positive nat.
-*)
+ clear H1.
+ lazymatch goal with
+ | [ H : context[(_ < ?x)%Z] |- _ ] => replace x with (Z.of_nat (Z.to_nat x)) in H
+ end.
+ 2: { apply Z2Nat.id; apply Z.pow_nonneg; lia. }
+
+ rewrite Z2Nat.inj_pow in H2; crush.
+ replace (Pos.to_nat 2) with 2%nat in H2 by reflexivity.
+ rewrite Nat2Z.id in H2.
+ rewrite <- positive_nat_Z in H2.
+ apply Nat2Z.inj_lt in H2.
+ assumption.
+Qed.
diff --git a/src/verilog/ValueInt.v b/src/verilog/ValueInt.v
new file mode 100644
index 0000000..151feef
--- /dev/null
+++ b/src/verilog/ValueInt.v
@@ -0,0 +1,162 @@
+(*
+ * CoqUp: 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/>.
+ *)
+
+(* begin hide *)
+From bbv Require Import Word.
+From bbv Require HexNotation WordScope.
+From Coq Require Import ZArith.ZArith FSets.FMapPositive Lia.
+From compcert Require Import lib.Integers common.Values.
+From coqup Require Import Coquplib.
+(* end hide *)
+
+(** * Value
+
+A [value] is a bitvector with a specific size. We are using the implementation
+of the bitvector by mit-plv/bbv, because it has many theorems that we can reuse.
+However, we need to wrap it with an [Inductive] so that we can specify and match
+on the size of the [value]. This is necessary so that we can easily store
+[value]s of different sizes in a list or in a map.
+
+Using the default [word], this would not be possible, as the size is part of the type. *)
+
+Definition value : Type := int.
+
+(** ** Value conversions
+
+Various conversions to different number types such as [N], [Z], [positive] and
+[int], where the last one is a theory of integers of powers of 2 in CompCert. *)
+
+Definition valueToNat (v : value) : nat :=
+ Z.to_nat (Int.unsigned v).
+
+Definition natToValue (n : nat) : value :=
+ Int.repr (Z.of_nat n).
+
+Definition valueToN (v : value) : N :=
+ Z.to_N (Int.unsigned v).
+
+Definition NToValue (n : N) : value :=
+ Int.repr (Z.of_N n).
+
+Definition ZToValue (z : Z) : value :=
+ Int.repr z.
+
+Definition valueToZ (v : value) : Z :=
+ Int.signed v.
+
+Definition uvalueToZ (v : value) : Z :=
+ Int.unsigned v.
+
+Definition posToValue (p : positive) : value :=
+ Int.repr (Z.pos p).
+
+Definition valueToPos (v : value) : positive :=
+ Z.to_pos (Int.unsigned v).
+
+Definition intToValue (i : Integers.int) : value := i.
+
+Definition valueToInt (i : value) : Integers.int := i.
+
+Definition ptrToValue (i : ptrofs) : value := Ptrofs.to_int i.
+
+Definition valueToPtr (i : value) : Integers.ptrofs :=
+ Ptrofs.of_int i.
+
+Definition valToValue (v : Values.val) : option value :=
+ match v with
+ | Values.Vint i => Some (intToValue i)
+ | Values.Vptr b off => Some (ptrToValue off)
+ | Values.Vundef => Some (ZToValue 0%Z)
+ | _ => None
+ end.
+
+(** Convert a [value] to a [bool], so that choices can be made based on the
+result. This is also because comparison operators will give back [value] instead
+of [bool], so if they are in a condition, they will have to be converted before
+they can be used. *)
+
+Definition valueToBool (v : value) : bool :=
+ if Z.eqb (uvalueToZ v) 0 then false else true.
+
+Definition boolToValue (b : bool) : value :=
+ natToValue (if b then 1 else 0).
+
+(** ** Arithmetic operations *)
+
+Definition unify_word (sz1 sz2 : nat) (w1 : word sz2): sz1 = sz2 -> word sz1.
+intros; subst; assumption. Defined.
+
+Lemma unify_word_unfold :
+ forall sz w,
+ unify_word sz sz w eq_refl = w.
+Proof. auto. Qed.
+
+Inductive val_value_lessdef: val -> value -> Prop :=
+| val_value_lessdef_int:
+ forall i v',
+ i = valueToInt v' ->
+ val_value_lessdef (Vint i) v'
+| val_value_lessdef_ptr:
+ forall b off v',
+ off = valueToPtr v' ->
+ val_value_lessdef (Vptr b off) v'
+| lessdef_undef: forall v, val_value_lessdef Vundef v.
+
+Inductive opt_val_value_lessdef: option val -> value -> Prop :=
+| opt_lessdef_some:
+ forall v v', val_value_lessdef v v' -> opt_val_value_lessdef (Some v) v'
+| opt_lessdef_none: forall v, opt_val_value_lessdef None v.
+
+Lemma valueToZ_ZToValue :
+ forall z,
+ (Int.min_signed <= z <= Int.max_signed)%Z ->
+ valueToZ (ZToValue z) = z.
+Proof. auto using Int.signed_repr. Qed.
+
+Lemma uvalueToZ_ZToValue :
+ forall z,
+ (0 <= z <= Int.max_unsigned)%Z ->
+ uvalueToZ (ZToValue z) = z.
+Proof. auto using Int.unsigned_repr. Qed.
+
+Lemma valueToPos_posToValue :
+ forall v,
+ 0 <= Z.pos v <= Int.max_unsigned ->
+ valueToPos (posToValue v) = v.
+Proof.
+ unfold valueToPos, posToValue.
+ intros. rewrite Int.unsigned_repr.
+ apply Pos2Z.id. assumption.
+Qed.
+
+Lemma valueToInt_intToValue :
+ forall v,
+ valueToInt (intToValue v) = v.
+Proof. auto. Qed.
+
+Lemma valToValue_lessdef :
+ forall v v',
+ valToValue v = Some v' ->
+ val_value_lessdef v v'.
+Proof.
+ intros.
+ destruct v; try discriminate; constructor.
+ unfold valToValue in H. inversion H.
+ unfold valueToInt. unfold intToValue in H1. auto.
+ inv H. symmetry. unfold valueToPtr, ptrToValue. apply Ptrofs.of_int_to_int. trivial.
+Qed.
diff --git a/src/verilog/Verilog.v b/src/verilog/Verilog.v
index 555ddbd..06e250a 100644
--- a/src/verilog/Verilog.v
+++ b/src/verilog/Verilog.v
@@ -29,11 +29,9 @@ Require Import Lia.
Import ListNotations.
-From coqup Require Import common.Coquplib common.Show verilog.Value AssocMap Array.
-From compcert Require Integers Events.
-From compcert Require Import Errors Smallstep Globalenvs.
-
-Import HexNotationValue.
+From coqup Require Import common.Coquplib common.Show verilog.ValueInt IntegerExtra AssocMap Array.
+From compcert Require Events.
+From compcert Require Import Integers Errors Smallstep Globalenvs.
Local Open Scope assocmap.
@@ -80,7 +78,7 @@ Definition merge_arrs (new : assocmap_arr) (old : assocmap_arr) : assocmap_arr :
Definition arr_assocmap_lookup (a : assocmap_arr) (r : reg) (i : nat) : option value :=
match a ! r with
| None => None
- | Some arr => Some (Option.default (NToValue 32 0) (Option.join (array_get_error i arr)))
+ | Some arr => Some (Option.default (NToValue 0) (Option.join (array_get_error i arr)))
end.
Definition arr_assocmap_set (r : reg) (i : nat) (v : value) (a : assocmap_arr) : assocmap_arr :=
@@ -145,7 +143,8 @@ Inductive binop : Type :=
| Vxor : binop (** xor (binary [^|]) *)
| Vshl : binop (** shift left ([<<]) *)
| Vshr : binop (** shift right ([>>>]) *)
-| Vshru : binop. (** shift right unsigned ([>>]) *)
+| Vshru : binop (** shift right unsigned ([>>]) *)
+| Vror : binop. (** shift right unsigned ([>>]) *)
(** ** Unary Operators *)
@@ -156,16 +155,21 @@ Inductive unop : Type :=
(** ** Expressions *)
Inductive expr : Type :=
-| Vlit : value -> expr
-| Vvar : reg -> expr
-| Vvari : reg -> expr -> expr
+| Vlit : value -> expr (** literal *)
+| Vvar : reg -> expr (** reg *)
+| Vvarb0 : reg -> expr (** 1st byte projection of reg *)
+| Vvarb1 : reg -> expr
+| Vvarb2 : reg -> expr
+| Vvarb3 : reg -> expr
+| Vvari : reg -> expr -> expr (** array *)
| Vinputvar : reg -> expr
| Vbinop : binop -> expr -> expr -> expr
| Vunop : unop -> expr -> expr
-| Vternary : expr -> expr -> expr -> expr.
+| Vternary : expr -> expr -> expr -> expr
+| Vload : reg -> expr -> expr. (** 4-byte concatenation load *)
-Definition posToExpr (sz : nat) (p : positive) : expr :=
- Vlit (posToValue sz p).
+Definition posToExpr (p : positive) : expr :=
+ Vlit (posToValue p).
(** ** Statements *)
@@ -245,12 +249,9 @@ Definition program := AST.program fundef unit.
(** Convert a [positive] to an expression directly, setting it to the right
size. *)
Definition posToLit (p : positive) : expr :=
- Vlit (posToValueAuto p).
-
-Coercion Vlit : value >-> expr.
-Coercion Vvar : reg >-> expr.
+ Vlit (posToValue p).
-Definition fext := assocmap.
+Definition fext := unit.
Definition fextclk := nat -> fext.
(** ** State
@@ -298,81 +299,99 @@ Inductive state : Type :=
(m : module)
(args : list value), state.
-Definition binop_run (op : binop) : forall v1 v2 : value, vsize v1 = vsize v2 -> value :=
+Definition binop_run (op : binop) (v1 v2 : value) : option value :=
match op with
- | Vadd => vplus
- | Vsub => vminus
- | Vmul => vmul
- | Vdiv => vdivs
- | Vdivu => vdiv
- | Vmod => vmods
- | Vmodu => vmod
- | Vlt => vlts
- | Vltu => vlt
- | Vgt => vgts
- | Vgtu => vgt
- | Vle => vles
- | Vleu => vle
- | Vge => vges
- | Vgeu => vge
- | Veq => veq
- | Vne => vne
- | Vand => vand
- | Vor => vor
- | Vxor => vxor
- | Vshl => vshl
- | Vshr => vshr
- | Vshru => vshr (* FIXME: should not be the same operation. *)
+ | Vadd => Some (Int.add v1 v2)
+ | Vsub => Some (Int.sub v1 v2)
+ | Vmul => Some (Int.mul v1 v2)
+ | Vdiv => if Int.eq v2 Int.zero
+ || Int.eq v1 (Int.repr Int.min_signed) && Int.eq v2 Int.mone
+ then None
+ else Some (Int.divs v1 v2)
+ | Vdivu => if Int.eq v2 Int.zero then None else Some (Int.divu v1 v2)
+ | Vmod => if Int.eq v2 Int.zero
+ || Int.eq v1 (Int.repr Int.min_signed) && Int.eq v2 Int.mone
+ then None
+ else Some (Int.mods v1 v2)
+ | Vmodu => if Int.eq v2 Int.zero then None else Some (Int.modu v1 v2)
+ | Vlt => Some (boolToValue (Int.lt v1 v2))
+ | Vltu => Some (boolToValue (Int.ltu v1 v2))
+ | Vgt => Some (boolToValue (Int.lt v2 v1))
+ | Vgtu => Some (boolToValue (Int.ltu v2 v1))
+ | Vle => Some (boolToValue (negb (Int.lt v2 v1)))
+ | Vleu => Some (boolToValue (negb (Int.ltu v2 v1)))
+ | Vge => Some (boolToValue (negb (Int.lt v1 v2)))
+ | Vgeu => Some (boolToValue (negb (Int.ltu v1 v2)))
+ | Veq => Some (boolToValue (Int.eq v1 v2))
+ | Vne => Some (boolToValue (negb (Int.eq v1 v2)))
+ | Vand => Some (Int.and v1 v2)
+ | Vor => Some (Int.or v1 v2)
+ | Vxor => Some (Int.xor v1 v2)
+ | Vshl => Some (Int.shl v1 v2)
+ | Vshr => Some (Int.shr v1 v2)
+ | Vshru => Some (Int.shru v1 v2)
+ | Vror => Some (Int.ror v1 v2)
end.
-Definition unop_run (op : unop) : value -> value :=
+Definition unop_run (op : unop) (v1 : value) : value :=
match op with
- | Vneg => vnot
- | Vnot => vbitneg
+ | Vneg => Int.neg v1
+ | Vnot => Int.not v1
end.
Inductive expr_runp : fext -> assocmap -> assocmap_arr -> expr -> value -> Prop :=
| erun_Vlit :
- forall fext reg stack v,
- expr_runp fext reg stack (Vlit v) v
+ forall fext asr asa v,
+ expr_runp fext asr asa (Vlit v) v
| erun_Vvar :
- forall fext reg stack v r,
- reg#r = v ->
- expr_runp fext reg stack (Vvar r) v
+ forall fext asr asa v r,
+ asr#r = v ->
+ expr_runp fext asr asa (Vvar r) v
+ | erun_Vvarb0 :
+ forall fext asr asa v r,
+ asr#r = v ->
+ expr_runp fext asr asa (Vvarb0 r) (IntExtra.ibyte0 v)
+ | erun_Vvarb1 :
+ forall fext asr asa v r,
+ asr#r = v ->
+ expr_runp fext asr asa (Vvarb1 r) (IntExtra.ibyte1 v)
+ | erun_Vvarb2 :
+ forall fext asr asa v r,
+ asr#r = v ->
+ expr_runp fext asr asa (Vvarb2 r) (IntExtra.ibyte2 v)
+ | erun_Vvarb3 :
+ forall fext asr asa v r,
+ asr#r = v ->
+ expr_runp fext asr asa (Vvarb3 r) (IntExtra.ibyte3 v)
| erun_Vvari :
- forall fext reg stack v iexp i r,
- expr_runp fext reg stack iexp i ->
- arr_assocmap_lookup stack r (valueToNat i) = Some v ->
- expr_runp fext reg stack (Vvari r iexp) v
- | erun_Vinputvar :
- forall fext reg stack r v,
- fext!r = Some v ->
- expr_runp fext reg stack (Vinputvar r) v
+ forall fext asr asa v iexp i r,
+ expr_runp fext asr asa iexp i ->
+ arr_assocmap_lookup asa r (valueToNat i) = Some v ->
+ expr_runp fext asr asa (Vvari r iexp) v
| erun_Vbinop :
- forall fext reg stack op l r lv rv oper EQ resv,
- expr_runp fext reg stack l lv ->
- expr_runp fext reg stack r rv ->
- oper = binop_run op ->
- resv = oper lv rv EQ ->
- expr_runp fext reg stack (Vbinop op l r) resv
+ forall fext asr asa op l r lv rv resv,
+ expr_runp fext asr asa l lv ->
+ expr_runp fext asr asa r rv ->
+ Some resv = binop_run op lv rv ->
+ expr_runp fext asr asa (Vbinop op l r) resv
| erun_Vunop :
- forall fext reg stack u vu op oper resv,
- expr_runp fext reg stack u vu ->
+ forall fext asr asa u vu op oper resv,
+ expr_runp fext asr asa u vu ->
oper = unop_run op ->
resv = oper vu ->
- expr_runp fext reg stack (Vunop op u) resv
+ expr_runp fext asr asa (Vunop op u) resv
| erun_Vternary_true :
- forall fext reg stack c ts fs vc vt,
- expr_runp fext reg stack c vc ->
- expr_runp fext reg stack ts vt ->
+ forall fext asr asa c ts fs vc vt,
+ expr_runp fext asr asa c vc ->
+ expr_runp fext asr asa ts vt ->
valueToBool vc = true ->
- expr_runp fext reg stack (Vternary c ts fs) vt
+ expr_runp fext asr asa (Vternary c ts fs) vt
| erun_Vternary_false :
- forall fext reg stack c ts fs vc vf,
- expr_runp fext reg stack c vc ->
- expr_runp fext reg stack fs vf ->
+ forall fext asr asa c ts fs vc vf,
+ expr_runp fext asr asa c vc ->
+ expr_runp fext asr asa fs vf ->
valueToBool vc = false ->
- expr_runp fext reg stack (Vternary c ts fs) vf.
+ expr_runp fext asr asa (Vternary c ts fs) vf.
Hint Constructors expr_runp : verilog.
Definition handle_opt {A : Type} (err : errmsg) (val : option A)
@@ -391,11 +410,11 @@ Definition handle_def {A : Type} (a : A) (val : option A)
Local Open Scope error_monad_scope.
-Definition access_fext (f : fext) (r : reg) : res value :=
+(*Definition access_fext (f : fext) (r : reg) : res value :=
match AssocMap.get r f with
| Some v => OK v
- | _ => OK (ZToValue 1 0)
- end.
+ | _ => OK (ZToValue 0)
+ end.*)
(* TODO FIX Vvar case without default *)
(*Fixpoint expr_run (assoc : assocmap) (e : expr)
@@ -432,8 +451,8 @@ Inductive location : Type :=
| LocArray (_ : reg) (_ : nat).
Inductive location_is : fext -> assocmap -> assocmap_arr -> expr -> location -> Prop :=
-| Base : forall f asr asa r, location_is f asr asa (Vvar r) (LocReg r)
-| Indexed : forall f asr asa r iexp iv,
+| Reg : forall f asr asa r, location_is f asr asa (Vvar r) (LocReg r)
+| RegIndexed : forall f asr asa r iexp iv,
expr_runp f asr asa iexp iv ->
location_is f asr asa (Vvari r iexp) (LocArray r (valueToNat iv)).
@@ -519,7 +538,7 @@ Inductive stmnt_runp: fext -> reg_associations -> arr_associations ->
forall f st1 st2 asr0 asa0 asr1 asa1 asr2 asa2,
stmnt_runp f asr0 asa0 st1 asr1 asa1 ->
stmnt_runp f asr1 asa1 st2 asr2 asa2 ->
- stmnt_runp f asr0 asa1 (Vseq st1 st2) asr2 asa2
+ stmnt_runp f asr0 asa0 (Vseq st1 st2) asr2 asa2
| stmnt_runp_Vcond_true:
forall asr0 asa0 asr1 asa1 f c vc stt stf,
expr_runp f asr0.(assoc_blocking) asa0.(assoc_blocking) c vc ->
@@ -530,7 +549,7 @@ Inductive stmnt_runp: fext -> reg_associations -> arr_associations ->
forall asr0 asa0 asr1 asa1 f c vc stt stf,
expr_runp f asr0.(assoc_blocking) asa0.(assoc_blocking) c vc ->
valueToBool vc = false ->
- stmnt_runp f asr0 asa0 stt asr1 asa1 ->
+ stmnt_runp f asr0 asa0 stf asr1 asa1 ->
stmnt_runp f asr0 asa0 (Vcond c stt stf) asr1 asa1
| stmnt_runp_Vcase_nomatch:
forall e ve asr0 asa0 f asr1 asa1 me mve sc cs def,
@@ -599,7 +618,7 @@ Inductive mi_stepp : fext -> reg_associations -> arr_associations ->
module_item -> reg_associations -> arr_associations -> Prop :=
| mi_stepp_Valways :
forall f sr0 sa0 st sr1 sa1 c,
- stmnt_runp f sr0 sa0 st sr1 sa0 ->
+ stmnt_runp f sr0 sa0 st sr1 sa1 ->
mi_stepp f sr0 sa0 (Valways c st) sr1 sa1
| mi_stepp_Valways_ff :
forall f sr0 sa0 st sr1 sa1 c,
@@ -610,8 +629,8 @@ Inductive mi_stepp : fext -> reg_associations -> arr_associations ->
stmnt_runp f sr0 sa0 st sr1 sa1 ->
mi_stepp f sr0 sa0 (Valways_comb c st) sr1 sa1
| mi_stepp_Vdecl :
- forall f sr sa lhs rhs io,
- mi_stepp f sr sa (Vdeclaration (Vdecl io lhs rhs)) sr sa.
+ forall f sr sa d,
+ mi_stepp f sr sa (Vdeclaration d) sr sa.
Hint Constructors mi_stepp : verilog.
Inductive mis_stepp : fext -> reg_associations -> arr_associations ->
@@ -650,11 +669,11 @@ Fixpoint mi_run (f : fextclk) (assoc : assocmap) (m : list module_item) (n : nat
assumed to be the starting state of the module, and may have to be changed if
other arguments to the module are also to be supported. *)
-Definition initial_fextclk (m : module) : fextclk :=
+(*Definition initial_fextclk (m : module) : fextclk :=
fun x => match x with
- | S O => (AssocMap.set (mod_reset m) (ZToValue 1 1) empty_assocmap)
- | _ => (AssocMap.set (mod_reset m) (ZToValue 1 0) empty_assocmap)
- end.
+ | S O => (AssocMap.set (mod_reset m) (ZToValue 1) empty_assocmap)
+ | _ => (AssocMap.set (mod_reset m) (ZToValue 0) empty_assocmap)
+ end.*)
(*Definition module_run (n : nat) (m : module) : res assocmap :=
mi_run (initial_fextclk m) empty_assocmap (mod_body m) n.*)
@@ -713,6 +732,8 @@ Definition empty_stack (m : module) : assocmap_arr :=
Inductive step : genv -> state -> Events.trace -> state -> Prop :=
| step_module :
forall asr asa asr' asa' basr1 nasr1 basa1 nasa1 f stval pstval m sf st g ist,
+ asr!(m.(mod_reset)) = Some (ZToValue 0) ->
+ asr!(m.(mod_finish)) = Some (ZToValue 0) ->
asr!(m.(mod_st)) = Some ist ->
valueToPos ist = st ->
mis_stepp f (mkassociations asr empty_assocmap)
@@ -727,22 +748,23 @@ Inductive step : genv -> state -> Events.trace -> state -> Prop :=
step g (State sf m st asr asa) Events.E0 (State sf m pstval asr' asa')
| step_finish :
forall asr asa sf retval m st g,
- asr!(m.(mod_finish)) = Some (1'h"1") ->
+ asr!(m.(mod_finish)) = Some (ZToValue 1) ->
asr!(m.(mod_return)) = Some retval ->
step g (State sf m st asr asa) Events.E0 (Returnstate sf retval)
| step_call :
forall g res m args,
step g (Callstate res m args) Events.E0
(State res m m.(mod_entrypoint)
- (AssocMap.set m.(mod_st) (posToValue 32 m.(mod_entrypoint))
- (init_params args m.(mod_args)))
+ (AssocMap.set (mod_reset m) (ZToValue 0)
+ (AssocMap.set (mod_finish m) (ZToValue 0)
+ (AssocMap.set m.(mod_st) (posToValue m.(mod_entrypoint))
+ (init_params args m.(mod_args)))))
(empty_stack m))
| step_return :
forall g m asr i r sf pc mst asa,
mst = mod_st m ->
step g (Returnstate (Stackframe r m pc asr asa :: sf) i) Events.E0
- (State sf m pc ((asr # mst <- (posToValue 32 pc)) # r <- i)
- (empty_stack m)).
+ (State sf m pc ((asr # mst <- (posToValue pc)) # r <- i) asa).
Hint Constructors step : verilog.
Inductive initial_state (p: program): state -> Prop :=
@@ -761,3 +783,138 @@ Inductive final_state : state -> Integers.int -> Prop :=
Definition semantics (m : program) :=
Smallstep.Semantics step (initial_state m) final_state
(Globalenvs.Genv.globalenv m).
+
+Lemma expr_runp_determinate :
+ forall f e asr asa v,
+ expr_runp f asr asa e v ->
+ forall v',
+ expr_runp f asr asa e v' ->
+ v' = v.
+Proof.
+ induction e; intros;
+
+ repeat (try match goal with
+ | [ H : expr_runp _ _ _ (Vlit _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvar _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvarb0 _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvarb1 _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvarb2 _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvarb3 _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vvari _ _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vinputvar _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vbinop _ _ _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vunop _ _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vternary _ _ _) _ |- _ ] => invert H
+ | [ H : expr_runp _ _ _ (Vload _ _) _ |- _ ] => invert H
+
+ | [ H1 : forall asr asa v, expr_runp _ asr asa ?e v -> _,
+ H2 : expr_runp _ _ _ ?e _ |- _ ] =>
+ learn (H1 _ _ _ H2)
+ | [ H1 : forall v, expr_runp _ ?asr ?asa ?e v -> _,
+ H2 : expr_runp _ ?asr ?asa ?e _ |- _ ] =>
+ learn (H1 _ H2)
+ end; crush).
+Qed.
+Hint Resolve expr_runp_determinate : verilog.
+
+Lemma location_is_determinate :
+ forall f asr asa e l,
+ location_is f asr asa e l ->
+ forall l',
+ location_is f asr asa e l' ->
+ l' = l.
+Proof.
+ induction 1; intros;
+
+ repeat (try match goal with
+ | [ H : location_is _ _ _ _ _ |- _ ] => invert H
+ | [ H1 : expr_runp _ ?asr ?asa ?e _,
+ H2 : expr_runp _ ?asr ?asa ?e _ |- _ ] =>
+ learn (expr_runp_determinate H1 H2)
+ end; crush).
+Qed.
+
+Lemma stmnt_runp_determinate :
+ forall f s asr0 asa0 asr1 asa1,
+ stmnt_runp f asr0 asa0 s asr1 asa1 ->
+ forall asr1' asa1',
+ stmnt_runp f asr0 asa0 s asr1' asa1' ->
+ asr1' = asr1 /\ asa1' = asa1.
+ induction 1; intros;
+
+ repeat (try match goal with
+ | [ H : stmnt_runp _ _ _ (Vseq _ _) _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ (Vnonblock _ _) _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ (Vblock _ _) _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ Vskip _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ (Vcond _ _ _) _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ (Vcase _ (_ :: _) _) _ _ |- _ ] => invert H
+ | [ H : stmnt_runp _ _ _ (Vcase _ [] _) _ _ |- _ ] => invert H
+
+ | [ H1 : expr_runp _ ?asr ?asa ?e _,
+ H2 : expr_runp _ ?asr ?asa ?e _ |- _ ] =>
+ learn (expr_runp_determinate H1 H2)
+
+ | [ H1 : location_is _ ?asr ?asa ?e _,
+ H2 : location_is _ ?asr ?asa ?e _ |- _ ] =>
+ learn (location_is_determinate H1 H2)
+
+ | [ H1 : forall asr1 asa1, stmnt_runp _ ?asr0 ?asa0 ?s asr1 asa1 -> _,
+ H2 : stmnt_runp _ ?asr0 ?asa0 ?s _ _ |- _ ] =>
+ learn (H1 _ _ H2)
+ end; crush).
+Qed.
+Hint Resolve stmnt_runp_determinate : verilog.
+
+Lemma mi_stepp_determinate :
+ forall f asr0 asa0 m asr1 asa1,
+ mi_stepp f asr0 asa0 m asr1 asa1 ->
+ forall asr1' asa1',
+ mi_stepp f asr0 asa0 m asr1' asa1' ->
+ asr1' = asr1 /\ asa1' = asa1.
+Proof.
+ intros. destruct m; invert H; invert H0;
+
+ repeat (try match goal with
+ | [ H1 : stmnt_runp _ ?asr0 ?asa0 ?s _ _,
+ H2 : stmnt_runp _ ?asr0 ?asa0 ?s _ _ |- _ ] =>
+ learn (stmnt_runp_determinate H1 H2)
+ end; crush).
+Qed.
+
+Lemma mis_stepp_determinate :
+ forall f asr0 asa0 m asr1 asa1,
+ mis_stepp f asr0 asa0 m asr1 asa1 ->
+ forall asr1' asa1',
+ mis_stepp f asr0 asa0 m asr1' asa1' ->
+ asr1' = asr1 /\ asa1' = asa1.
+Proof.
+ induction 1; intros;
+
+ repeat (try match goal with
+ | [ H : mis_stepp _ _ _ [] _ _ |- _ ] => invert H
+ | [ H : mis_stepp _ _ _ ( _ :: _ ) _ _ |- _ ] => invert H
+
+ | [ H1 : mi_stepp _ ?asr0 ?asa0 ?s _ _,
+ H2 : mi_stepp _ ?asr0 ?asa0 ?s _ _ |- _ ] =>
+ learn (mi_stepp_determinate H1 H2)
+
+ | [ H1 : forall asr1 asa1, mis_stepp _ ?asr0 ?asa0 ?m asr1 asa1 -> _,
+ H2 : mis_stepp _ ?asr0 ?asa0 ?m _ _ |- _ ] =>
+ learn (H1 _ _ H2)
+ end; crush).
+Qed.
+
+Lemma semantics_determinate :
+ forall (p: program), Smallstep.determinate (semantics p).
+Proof.
+ intros. constructor; set (ge := Globalenvs.Genv.globalenv p); simplify.
+ - invert H; invert H0; constructor. (* Traces are always empty *)
+ - invert H; invert H0; crush. assert (f = f0) by (destruct f; destruct f0; auto); subst.
+ pose proof (mis_stepp_determinate H5 H15).
+ crush.
+ - constructor. invert H; crush.
+ - invert H; invert H0; unfold ge0, ge1 in *; crush.
+ - red; simplify; intro; invert H0; invert H; crush.
+ - invert H; invert H0; crush.
+Qed.