aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md6
-rw-r--r--driver/CoqupDriver.ml75
-rw-r--r--src/Compiler.v4
-rw-r--r--src/Simulator.v32
-rw-r--r--src/common/Coquplib.v11
-rw-r--r--src/extraction/Extraction.v6
-rw-r--r--src/translation/Veriloggen.v128
-rw-r--r--src/verilog/PrintVerilog.ml78
-rw-r--r--src/verilog/PrintVerilog.mli2
-rw-r--r--src/verilog/Value.v217
-rw-r--r--src/verilog/Verilog.v395
12 files changed, 798 insertions, 158 deletions
diff --git a/Makefile b/Makefile
index 0c26d57..1d328ec 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ COQMAKE := "$(COQBIN)coq_makefile"
COQUPDIRS := translation common verilog
VSSUBDIR := $(foreach d, $(COQUPDIRS), src/$(d)/*.v)
-VS := src/Compiler.v $(VSSUBDIR)
+VS := src/Compiler.v src/Simulator.v $(VSSUBDIR)
PREFIX ?= .
diff --git a/README.md b/README.md
index f6d8019..df65f8c 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ Which will install the binary in `./bin/coqup` by default. However, this can be
To test out `coqup` you can try the following examples which are in the test folder using the following:
``` shell
-./bin/coqup --hls test/loop.c -o loop.v
-./bin/coqup --hls test/conditional.c -o conditional.v
-./bin/coqup --hls test/add.c -o add.v
+./bin/coqup test/loop.c -o loop.v
+./bin/coqup test/conditional.c -o conditional.v
+./bin/coqup test/add.c -o add.v
```
diff --git a/driver/CoqupDriver.ml b/driver/CoqupDriver.ml
index 0a4f84f..80b4145 100644
--- a/driver/CoqupDriver.ml
+++ b/driver/CoqupDriver.ml
@@ -1,5 +1,15 @@
-(*
- * CoqUp: Verified high-level synthesis.
+(* *********************************************************************)
+(* *)
+(* The Compcert verified compiler *)
+(* *)
+(* Xavier Leroy, INRIA Paris-Rocquencourt *)
+(* *)
+(* Copyright Institut National de Recherche en Informatique et en *)
+(* Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* *)
+(* *********************************************************************)
+(* CoqUp: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -17,6 +27,7 @@
*)
open Printf
+open Coqup.Camlcoq
open Coqup.Commandline
open Coqup.Clflags
open Coqup.CommonOptions
@@ -28,6 +39,7 @@ open Coqup.Linker
open Coqup.Diagnostics
(* Coqup flags *)
+let option_simulate = ref false
let option_hls = ref true
(* Name used for version string etc. *)
@@ -37,7 +49,7 @@ let tool_name = "C verified high-level synthesis"
let sdump_suffix = ref ".json"
let nolink () =
- !option_c || !option_S || !option_E || !option_interp
+ !option_c || !option_S || !option_E || !option_interp || !option_hls
let object_filename sourcename suff =
if nolink () then
@@ -63,17 +75,47 @@ let compile_c_file sourcename ifile ofile =
set_dest Coqup.AsmToJSON.destination option_sdump !sdump_suffix;
(* Parse the ast *)
let csyntax = parse_c_file sourcename ifile in
- (* Convert to Asm *)
- let verilog =
- match Coqup.Compiler0.transf_hls csyntax with
- | Coqup.Errors.OK v ->
+ if not !option_hls then begin
+ (* Convert to Asm *)
+ let asm =
+ match Coqup.Compiler.apply_partial
+ (Coqup.Compiler.transf_c_program csyntax)
+ Coqup.Asmexpand.expand_program with
+ | Coqup.Errors.OK asm ->
+ asm
+ | Coqup.Errors.Error msg ->
+ let loc = file_loc sourcename in
+ fatal_error loc "%a" print_error msg in
+ (* Dump Asm in binary and JSON format *)
+ Coqup.AsmToJSON.print_if asm sourcename;
+ (* Print Asm in text form *)
+ let oc = open_out ofile in
+ Coqup.PrintAsm.print_program oc asm;
+ close_out oc
+ end else begin
+ let verilog =
+ match Coqup.Compiler0.transf_hls csyntax with
+ | Coqup.Errors.OK v ->
v
- | Coqup.Errors.Error msg ->
- let loc = file_loc sourcename in
+ | Coqup.Errors.Error msg ->
+ let loc = file_loc sourcename in
fatal_error loc "%a" print_error msg in
- let oc = open_out ofile in
- Coqup.PrintVerilog.print_program oc verilog;
- close_out oc
+ if not !option_simulate then begin
+ let oc = open_out ofile in
+ Coqup.PrintVerilog.print_program oc verilog;
+ close_out oc
+ end else begin
+ print_endline "Simulating";
+ let result =
+ match Coqup.Simulator.simulate (Nat.of_int 100) verilog with
+ | Coqup.Errors.OK r -> r
+ | Coqup.Errors.Error msg ->
+ let loc = file_loc sourcename in
+ fatal_error loc "%a" print_error msg in
+ printf "Length: %d\n" (List.length result);
+ Coqup.PrintVerilog.print_result result
+ end
+ end
(* From C source to asm *)
@@ -83,7 +125,7 @@ let compile_i_file sourcename preproname =
let csyntax = parse_c_file sourcename preproname in
Coqup.Interp.execute csyntax;
""
- end else if !option_S then begin
+ end else if !option_hls then begin
compile_c_file sourcename preproname
(output_filename ~final:true sourcename ".c" ".v");
""
@@ -183,6 +225,7 @@ Processing options:
-S Compile to assembler only, save result in <file>.s
-o <file> Generate output in <file>
--no-hls Do not use HLS and generate standard flow.
+ --simulate Simulate the result with the Verilog semantics.
|} ^
prepro_help ^
language_support_help ^
@@ -281,7 +324,9 @@ let cmdline_actions =
Exact "-help", Unit print_usage_and_exit;
Exact "--help", Unit print_usage_and_exit;] @
(* Use HLS *)
- [Exact "--no-hls", Unset option_hls;]
+ [Exact "--no-hls", Unset option_hls;
+ Exact "--simulate", Set option_simulate;
+ ]
(* Getting version info *)
@ version_options tool_name @
(* Enforcing CompCert build numbers for QSKs and mnemonics dump *)
@@ -294,7 +339,7 @@ let cmdline_actions =
(* Processing options *)
[ Exact "-c", Set option_c;
Exact "-E", Set option_E;
- Exact "--hls", Set option_S;
+ Exact "-S", Set option_S;
Exact "-o", String(fun s -> option_o := Some s);
Prefix "-o", Self (fun s -> let s = String.sub s 2 ((String.length s) - 2) in
option_o := Some s);]
diff --git a/src/Compiler.v b/src/Compiler.v
index 5b4ef0a..697732d 100644
--- a/src/Compiler.v
+++ b/src/Compiler.v
@@ -1,4 +1,4 @@
-(*
+(* -*- mode: coq -*-
* CoqUp: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -74,7 +74,7 @@ Proof.
intros. destruct x; simpl. rewrite print_identity. auto. auto.
Qed.
-Definition transf_backend (r : RTL.program) : res Verilog.module :=
+Definition transf_backend (r : RTL.program) : res Verilog.module :=
OK r
@@@ Veriloggen.transf_program.
diff --git a/src/Simulator.v b/src/Simulator.v
new file mode 100644
index 0000000..3c5aca0
--- /dev/null
+++ b/src/Simulator.v
@@ -0,0 +1,32 @@
+(* -*- mode: coq -*-
+ * 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/>.
+ *)
+
+From Coq Require Import FSets.FMapPositive.
+
+From compcert Require Import Errors.
+
+From coqup Require Compiler Verilog Value.
+From coqup Require Import Coquplib.
+
+Local Open Scope error_monad_scope.
+
+Definition simulate (n : nat) (m : Verilog.module) : res (list (positive * Value.value)) :=
+ do map <- Verilog.module_run n m;
+ OK (PositiveMap.elements map).
+
+Local Close Scope error_monad_scope.
diff --git a/src/common/Coquplib.v b/src/common/Coquplib.v
index 666d740..47360d6 100644
--- a/src/common/Coquplib.v
+++ b/src/common/Coquplib.v
@@ -65,6 +65,17 @@ Definition liftA2 {T : Type} (f : T -> T -> T) (a : option T) (b : option T) : o
| _ => None
end.
+Definition bind {A B : Type} (f : option A) (g : A -> option B) : option B :=
+ match f with
+ | Some a => g a
+ | _ => None
+ end.
+
+Module Notation.
+Notation "'do' X <- A ; B" := (bind A (fun X => B))
+ (at level 200, X ident, A at level 100, B at level 200).
+End Notation.
+
End Option.
Parameter debug_print : string -> unit.
diff --git a/src/extraction/Extraction.v b/src/extraction/Extraction.v
index ff0b8ba..319e2eb 100644
--- a/src/extraction/Extraction.v
+++ b/src/extraction/Extraction.v
@@ -1,4 +1,4 @@
-(*
+(* -*- mode: coq -*-
* CoqUp: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*)
-From coqup Require Verilog Compiler.
+From coqup Require Verilog Value Compiler Simulator.
From Coq Require DecidableClass.
@@ -166,7 +166,7 @@ Set Extraction AccessOpaque.
Cd "src/extraction".
Separate Extraction
- Verilog.module Verilog.valueToZ coqup.Compiler.transf_hls
+ Verilog.module Value.uvalueToZ coqup.Compiler.transf_hls Simulator.simulate
Compiler.transf_c_program Compiler.transf_cminor_program
Cexec.do_initial_state Cexec.do_step Cexec.at_final_state
diff --git a/src/translation/Veriloggen.v b/src/translation/Veriloggen.v
index f0620bf..6aa94df 100644
--- a/src/translation/Veriloggen.v
+++ b/src/translation/Veriloggen.v
@@ -1,4 +1,4 @@
-(*
+(* -*- mode: coq -*-
* CoqUp: Verified high-level synthesis.
* Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -18,7 +18,7 @@
From Coq Require Import FSets.FMapPositive.
-From coqup Require Import Verilog Coquplib.
+From coqup Require Import Verilog Coquplib Value.
From compcert Require Errors Op AST Integers Maps.
From compcert Require Import RTL.
@@ -29,6 +29,11 @@ Definition node : Type := positive.
Definition reg : Type := positive.
Definition ident : Type := positive.
+Hint Resolve PositiveMap.gempty : verilog_state.
+Hint Resolve PositiveMap.gso : verilog_state.
+Hint Resolve PositiveMap.gss : verilog_state.
+Hint Resolve Ple_refl : verilog_state.
+
Inductive statetrans : Type :=
| StateGoto (p : node)
| StateCond (c : expr) (t f : node).
@@ -36,11 +41,13 @@ Inductive statetrans : Type :=
Definition valid_freshstate (stm: PositiveMap.t stmnt) (fs: node) :=
forall (n: node),
Plt n fs \/ stm!n = None.
+Hint Unfold valid_freshstate : verilog_state.
Definition states_have_transitions (stm: PositiveMap.t stmnt) (st: PositiveMap.t statetrans) :=
forall (n: node),
(forall x, stm!n = Some x -> exists y, st!n = Some y)
/\ (forall x, st!n = Some x -> exists y, stm!n = Some y).
+Hint Unfold states_have_transitions : verilog_state.
Record state: Type := mkstate {
st_freshreg: reg;
@@ -54,7 +61,8 @@ Record state: Type := mkstate {
Remark init_state_valid_freshstate:
valid_freshstate (PositiveMap.empty stmnt) 1%positive.
-Proof. intros. right. apply PositiveMap.gempty. Qed.
+Proof. auto with verilog_state. Qed.
+Hint Resolve init_state_valid_freshstate : verilog_state.
Remark init_state_states_have_transitions:
states_have_transitions (PositiveMap.empty stmnt) (PositiveMap.empty statetrans).
@@ -62,11 +70,12 @@ Proof.
unfold states_have_transitions.
split; intros; rewrite PositiveMap.gempty in H; discriminate.
Qed.
+Hint Resolve init_state_states_have_transitions : verilog_state.
Remark init_state_wf:
valid_freshstate (PositiveMap.empty stmnt) 1%positive
/\ states_have_transitions (PositiveMap.empty stmnt) (PositiveMap.empty statetrans).
-Proof. split; intros. apply init_state_valid_freshstate. apply init_state_states_have_transitions. Qed.
+Proof. auto with verilog_state. Qed.
Definition init_state : state :=
mkstate 1%positive
@@ -87,27 +96,24 @@ Inductive state_incr: state -> state -> Prop :=
s1.(st_statetrans)!n = None
\/ s2.(st_statetrans)!n = s1.(st_statetrans)!n) ->
state_incr s1 s2.
+Hint Constructors state_incr : verilog_state.
Lemma state_incr_refl:
forall s, state_incr s s.
-Proof. intros. apply state_incr_intro;
- try (apply Ple_refl);
- try (intros; right; reflexivity).
-Qed.
+Proof. auto with verilog_state. Qed.
Lemma state_incr_trans:
forall s1 s2 s3, state_incr s1 s2 -> state_incr s2 s3 -> state_incr s1 s3.
Proof.
- intros. inv H. inv H0. apply state_incr_intro.
- - apply Ple_trans with (st_freshreg s2); assumption.
- - apply Ple_trans with (st_freshstate s2); assumption.
+ intros. inv H. inv H0. apply state_incr_intro; eauto using Ple_trans.
- intros. destruct H3 with n.
- + left. assumption.
- + destruct H6 with n.
- * rewrite <- H0. left. assumption.
- * right. rewrite <- H0. apply H8.
+ + left; assumption.
+ + destruct H6 with n;
+ [ rewrite <- H0; left; assumption
+ | right; rewrite <- H0; apply H8
+ ].
- intros. destruct H4 with n.
- + left. assumption.
+ + left; assumption.
+ destruct H7 with n.
* rewrite <- H0. left. assumption.
* right. rewrite <- H0. apply H8.
@@ -280,6 +286,7 @@ Proof.
rewrite PositiveMap.gso.
apply (st_wf s). assumption.
Qed.
+Hint Resolve add_instr_valid_freshstate : verilog_state.
Remark add_instr_states_have_transitions:
forall (s: state) (n n': node) (st: stmnt),
@@ -299,6 +306,7 @@ Proof.
assert (H2 := st_wf s). inv H2. unfold states_have_transitions in H1.
destruct H1 with n0. apply H3 with x. assumption. assumption. assumption.
Qed.
+Hint Resolve add_instr_states_have_transitions : verilog_state.
Remark add_instr_state_wf:
forall (s: state) (n n': node) (st: stmnt) (LT: Plt n (st_freshstate s)),
@@ -306,10 +314,7 @@ Remark add_instr_state_wf:
/\ states_have_transitions
(PositiveMap.add n st s.(st_stm))
(PositiveMap.add n (StateGoto n') s.(st_statetrans)).
-Proof.
- split; intros. apply add_instr_valid_freshstate. assumption.
- apply add_instr_states_have_transitions.
-Qed.
+Proof. auto with verilog_state. Qed.
Lemma add_instr_state_incr :
forall s n n' st LT,
@@ -323,9 +328,9 @@ Lemma add_instr_state_incr :
s.(st_decl)
(add_instr_state_wf s n n' st LT)).
Proof.
- intros. apply state_incr_intro; intros; simpl; try reflexivity;
- destruct (peq n n0); try (subst; left; assumption);
- right; apply PositiveMap.gso; apply not_eq_sym; assumption.
+ constructor; intros;
+ try (simpl; destruct (peq n n0); subst);
+ auto with verilog_state.
Qed.
Definition check_empty_node_stm:
@@ -365,9 +370,7 @@ Definition add_reg (r: reg) (s: state) : state :=
Lemma add_reg_state_incr:
forall r s,
state_incr s (add_reg r s).
-Proof.
- intros. apply state_incr_intro; unfold add_reg; try right; reflexivity.
-Qed.
+Proof. auto with verilog_state. Qed.
Definition add_instr_reg (r: reg) (n: node) (n': node) (st: stmnt) : mon unit :=
do _ <- map_state (add_reg r) (add_reg_state_incr r);
@@ -382,9 +385,7 @@ Lemma change_decl_state_incr:
(st_statetrans s)
decl'
(st_wf s)).
-Proof.
- intros. apply state_incr_intro; simpl; try reflexivity; right; reflexivity.
-Qed.
+Proof. auto with verilog_state. Qed.
Lemma decl_io_state_incr:
forall s,
@@ -395,10 +396,7 @@ Lemma decl_io_state_incr:
(st_statetrans s)
(st_decl s)
(st_wf s)).
-Proof.
- intros. apply state_incr_intro; try right; try reflexivity.
- simpl. apply Ple_succ.
-Qed.
+Proof. constructor; simpl; auto using Ple_succ with verilog_state. Qed.
Definition decl_io (sz: nat): mon (reg * nat) :=
fun s => let r := s.(st_freshreg) in
@@ -430,17 +428,10 @@ Lemma add_branch_instr_states_have_transitions:
states_have_transitions (PositiveMap.add n Vskip (st_stm s))
(PositiveMap.add n (StateCond e n1 n2) (st_statetrans s)).
Proof.
- split; intros.
- - destruct (peq n0 n).
- + subst. exists (StateCond e n1 n2). apply PositiveMap.gss.
- + rewrite PositiveMap.gso. rewrite PositiveMap.gso in H.
- assert (H1 := (st_wf s)). inv H1. unfold states_have_transitions in H2.
- destruct H2 with n0. apply H1 with x. assumption. assumption. assumption.
- - destruct (peq n0 n).
- + subst. exists Vskip. apply PositiveMap.gss.
- + rewrite PositiveMap.gso. rewrite PositiveMap.gso in H.
- assert (H1 := (st_wf s)). inv H1. unfold states_have_transitions in H2.
- destruct H2 with n0. apply H3 with x. assumption. assumption. assumption.
+ split; intros; destruct (peq n0 n); subst; eauto with verilog_state;
+ rewrite PositiveMap.gso in *;
+ assert (H1 := (st_wf s)); inv H1; unfold states_have_transitions in H2;
+ destruct H2 with n0; try (apply H1 with x); try (apply H3 with x); assumption.
Qed.
Lemma add_branch_valid_freshstate:
@@ -448,11 +439,10 @@ Lemma add_branch_valid_freshstate:
Plt n (st_freshstate s) ->
valid_freshstate (PositiveMap.add n Vskip (st_stm s)) (st_freshstate s).
Proof.
- unfold valid_freshstate. intros. destruct (peq n0 n).
- - subst. left. assumption.
- - assert (H1 := st_wf s). destruct H1.
- unfold valid_freshstate in H0. rewrite PositiveMap.gso. apply H0.
- assumption.
+ unfold valid_freshstate; intros; destruct (peq n0 n).
+ - subst; auto.
+ - assert (H1 := st_wf s); destruct H1;
+ unfold valid_freshstate in H0; rewrite PositiveMap.gso; auto.
Qed.
Lemma add_branch_instr_st_wf:
@@ -462,8 +452,7 @@ Lemma add_branch_instr_st_wf:
/\ states_have_transitions (PositiveMap.add n Vskip (st_stm s))
(PositiveMap.add n (StateCond e n1 n2) (st_statetrans s)).
Proof.
- split; intros. apply add_branch_valid_freshstate. assumption.
- apply add_branch_instr_states_have_transitions.
+ auto using add_branch_valid_freshstate, add_branch_instr_states_have_transitions.
Qed.
Lemma add_branch_instr_state_incr:
@@ -478,8 +467,9 @@ Lemma add_branch_instr_state_incr:
(st_decl s)
(add_branch_instr_st_wf s e n n1 n2 LT)).
Proof.
- intros. apply state_incr_intro; simpl; try reflexivity; intros; destruct (peq n0 n);
- try (subst; left; assumption); right; apply PositiveMap.gso; assumption.
+ intros. apply state_incr_intro; simpl;
+ try (intros; destruct (peq n0 n); subst);
+ auto with verilog_state.
Qed.
Definition add_branch_instr (e: expr) (n n1 n2: node) : mon unit :=
@@ -517,27 +507,27 @@ Definition transf_instr (fin rtrn: reg) (ni: node * instruction) : mon unit :=
| Ireturn r =>
match r with
| Some r' =>
- add_instr n n (Vseq (block fin (Vlit (ZToValue 1%nat 1%Z)) :: block rtrn (Vvar r') :: nil))
+ add_instr n n (Vseq (block fin (Vlit (ZToValue 1%nat 1%Z))) (block rtrn (Vvar r')))
| None =>
- add_instr n n (Vseq (block fin (Vlit (ZToValue 1%nat 1%Z)) :: nil))
+ add_instr n n (block fin (Vlit (ZToValue 1%nat 1%Z)))
end
end
end.
Definition make_stm_cases (s : positive * stmnt) : expr * stmnt :=
- match s with (a, b) => (posToExpr a, b) end.
+ match s with (a, b) => (posToExpr 32 a, b) end.
Definition make_stm (r : reg) (s : PositiveMap.t stmnt) : stmnt :=
- Vcase (Vvar r) (map make_stm_cases (PositiveMap.elements s)).
+ Vcase (Vvar r) (map make_stm_cases (PositiveMap.elements s)) (Some Vskip).
Definition make_statetrans_cases (r : reg) (st : positive * statetrans) : expr * stmnt :=
match st with
- | (n, StateGoto n') => (posToExpr n, nonblock r (posToExpr n'))
- | (n, StateCond c n1 n2) => (posToExpr n, nonblock r (Vternary c (posToExpr n1) (posToExpr n2)))
+ | (n, StateGoto n') => (posToExpr 32 n, nonblock r (posToExpr 32 n'))
+ | (n, StateCond c n1 n2) => (posToExpr 32 n, nonblock r (Vternary c (posToExpr 32 n1) (posToExpr 32 n2)))
end.
Definition make_statetrans (r : reg) (s : PositiveMap.t statetrans) : stmnt :=
- Vcase (Vvar r) (map (make_statetrans_cases r) (PositiveMap.elements s)).
+ Vcase (Vvar r) (map (make_statetrans_cases r) (PositiveMap.elements s)) (Some Vskip).
Fixpoint allocate_regs (e : list (reg * nat)) {struct e} : list module_item :=
match e with
@@ -546,11 +536,11 @@ Fixpoint allocate_regs (e : list (reg * nat)) {struct e} : list module_item :=
end.
Definition make_module_items (entry: node) (clk st rst: reg) (s: state) : list module_item :=
- (Valways (Voredge (Vposedge clk) (Vposedge rst))
- (Vcond (Vbinop Veq (Vvar rst) (Vlit (ZToValue 1%nat 1%Z)))
- (nonblock st (posToExpr entry))
+ (Valways_ff (Vposedge clk)
+ (Vcond (Vbinop Veq (Vinputvar rst) (Vlit (ZToValue 1 1)))
+ (nonblock st (posToExpr 32 entry))
(make_statetrans st s.(st_statetrans))))
- :: (Valways Valledge (make_stm st s.(st_stm)))
+ :: (Valways_ff (Vposedge clk) (make_stm st s.(st_stm)))
:: (allocate_regs (PositiveMap.elements s.(st_decl))).
(** To start out with, the assumption is made that there is only one
@@ -584,18 +574,14 @@ Fixpoint main_function (main : ident) (flist : list (ident * AST.globdef fundef
Lemma max_state_valid_freshstate:
forall f,
valid_freshstate (st_stm init_state) (Pos.succ (max_pc_function f)).
-Proof.
- unfold valid_freshstate. intros. right. simpl. apply PositiveMap.gempty.
-Qed.
+Proof. unfold valid_freshstate; simpl; auto with verilog_state. Qed.
+Hint Resolve max_state_valid_freshstate : verilog_state.
Lemma max_state_st_wf:
forall f,
valid_freshstate (st_stm init_state) (Pos.succ (max_pc_function f))
/\ states_have_transitions (st_stm init_state) (st_statetrans init_state).
-Proof.
- split. apply max_state_valid_freshstate.
- apply init_state_states_have_transitions.
-Qed.
+Proof. auto with verilog_state. Qed.
Definition max_state (f: function) : state :=
mkstate (Pos.succ (max_reg_function f))
diff --git a/src/verilog/PrintVerilog.ml b/src/verilog/PrintVerilog.ml
index 292fcf2..17c0b16 100644
--- a/src/verilog/PrintVerilog.ml
+++ b/src/verilog/PrintVerilog.ml
@@ -1,4 +1,4 @@
-(*
+(* -*- mode: tuareg -*-
* CoqUp: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -17,6 +17,7 @@
*)
open Verilog
+open Value
open Datatypes
open Camlcoq
@@ -31,23 +32,32 @@ let fold_map f s = List.map f s |> concat
let pstr pp = fprintf pp "%s"
-let pprint_binop = function
- | Vadd -> " + "
- | Vsub -> " - "
- | Vmul -> " * "
- | Vdiv -> " / "
- | Vmod -> " % "
- | Vlt -> " < "
- | Vgt -> " > "
- | Vle -> " <= "
- | Vge -> " >= "
- | Veq -> " == "
- | Vne -> " != "
- | Vand -> " & "
- | Vor -> " | "
- | Vxor -> " ^ "
- | Vshl -> " << "
- | Vshr -> " >> "
+let pprint_binop l r =
+ let unsigned op = sprintf "{%s %s %s}" l op r in
+ let signed op = sprintf "{$signed(%s) %s $signed(%s)}" l op r in
+ function
+ | Vadd -> unsigned "+"
+ | Vsub -> unsigned "-"
+ | Vmul -> unsigned "*"
+ | Vdiv -> signed "/"
+ | Vdivu -> unsigned "/"
+ | Vmod -> signed "%"
+ | Vmodu -> unsigned "%"
+ | Vlt -> signed "<"
+ | Vltu -> unsigned "<"
+ | Vgt -> signed ">"
+ | Vgtu -> unsigned ">"
+ | Vle -> signed "<="
+ | Vleu -> unsigned "<="
+ | Vge -> signed ">="
+ | Vgeu -> unsigned ">="
+ | Veq -> unsigned "=="
+ | Vne -> unsigned "!="
+ | Vand -> unsigned "&"
+ | Vor -> unsigned "|"
+ | Vxor -> unsigned "^"
+ | Vshl -> unsigned "<<"
+ | Vshr -> unsigned ">>"
let unop = function
| Vneg -> " ~ "
@@ -55,25 +65,29 @@ 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 (valueToZ l))
+let literal l = sprintf "%d'd%d" (Nat.to_int l.vsize) (Z.to_int (uvalueToZ l))
let rec pprint_expr = function
| Vlit l -> literal l
| Vvar s -> register s
+ | Vinputvar s -> register s
| Vunop (u, e) -> concat ["("; unop u; pprint_expr e; ")"]
- | Vbinop (op, a, b) -> concat ["("; pprint_expr a; pprint_binop op; pprint_expr b; ")"]
+ | 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; ")"]
let rec pprint_stmnt i =
- let pprint_case (e, s) = concat [indent (i + 1); pprint_expr e; ":\n"; pprint_stmnt (i + 2) s]
+ let pprint_case (e, s) = concat [ indent (i + 1); pprint_expr e; ": begin\n"; pprint_stmnt (i + 2) s;
+ indent (i + 1); "end\n"
+ ]
in function
| Vskip -> concat [indent i; ";\n"]
- | Vseq s -> concat [indent i; "begin\n"; fold_map (pprint_stmnt (i+1)) s; indent i; "end\n"]
- | Vcond (e, st, sf) -> concat [ indent i; "if ("; pprint_expr e; ")\n";
- pprint_stmnt (i + 1) st; indent i; "else\n";
- pprint_stmnt (i + 1) sf
+ | Vseq (s1, s2) -> concat [ pprint_stmnt i s1; pprint_stmnt i s2]
+ | Vcond (e, st, sf) -> concat [ indent i; "if ("; pprint_expr e; ") begin\n";
+ pprint_stmnt (i + 1) st; indent i; "end else begin\n";
+ pprint_stmnt (i + 1) sf;
+ indent i; "end\n"
]
- | Vcase (e, es) -> concat [ indent i; "case ("; pprint_expr e; ")\n";
+ | Vcase (e, es, d) -> concat [ indent i; "case ("; pprint_expr e; ")\n";
fold_map pprint_case es; indent (i+1); "default:;\n";
indent i; "endcase\n"
]
@@ -97,10 +111,15 @@ let declare i t =
concat [ indent i; t; " ["; sprintf "%d" (Nat.to_int sz - 1); ":0] ";
register r; ";\n" ]
+(* TODO Fix always blocks, as they currently always print the same. *)
let pprint_module_item i = function
| Vdecl (r, sz) -> declare i "reg" (r, sz)
| Valways (e, s) ->
concat [indent i; "always "; pprint_edge_top i e; "\n"; pprint_stmnt (i+1) s]
+ | Valways_ff (e, s) ->
+ concat [indent i; "always "; pprint_edge_top i e; "\n"; pprint_stmnt (i+1) s]
+ | Valways_comb (e, s) ->
+ concat [indent i; "always "; pprint_edge_top i e; "\n"; pprint_stmnt (i+1) s]
let rec intersperse c = function
| [] -> []
@@ -154,3 +173,10 @@ let pprint_module i n m =
]
let print_program pp v = pstr pp (pprint_module 0 "main" v)
+
+let rec print_result =
+ function
+ | [] -> ()
+ | (r, v) :: ls ->
+ printf "%s -> %s\n" (register r) (literal v);
+ print_result ls
diff --git a/src/verilog/PrintVerilog.mli b/src/verilog/PrintVerilog.mli
index 181a9d2..b4d2937 100644
--- a/src/verilog/PrintVerilog.mli
+++ b/src/verilog/PrintVerilog.mli
@@ -17,3 +17,5 @@
*)
val print_program : out_channel -> Verilog.coq_module -> unit
+
+val print_result : (BinNums.positive * Value.value) list -> unit
diff --git a/src/verilog/Value.v b/src/verilog/Value.v
new file mode 100644
index 0000000..be6babf
--- /dev/null
+++ b/src/verilog/Value.v
@@ -0,0 +1,217 @@
+(* -*- mode: coq -*-
+ * 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 Coq Require Import ZArith.ZArith.
+From compcert Require Import lib.Integers.
+(* 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. *)
+
+Record value : Type :=
+ mkvalue {
+ vsize: nat;
+ vword: word vsize
+ }.
+
+(** ** 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 wordToValue : forall sz : nat, word sz -> value := mkvalue.
+
+Definition valueToWord : forall v : value, word (vsize v) := vword.
+
+Definition valueToNat (v : value) : nat :=
+ wordToNat (vword v).
+
+Definition natToValue sz (n : nat) : value :=
+ mkvalue sz (natToWord sz n).
+
+Definition valueToN (v : value) : N :=
+ wordToN (vword v).
+
+Definition NToValue sz (n : N) : value :=
+ mkvalue sz (NToWord sz n).
+
+Definition posToValue sz (p : positive) : value :=
+ mkvalue sz (posToWord sz p).
+
+Definition posToValueAuto (p : positive) : value :=
+ let size := Z.to_nat (Z.succ (log_inf p)) in
+ mkvalue size (Word.posToWord size p).
+
+Definition ZToValue (s : nat) (z : Z) : value :=
+ mkvalue s (ZToWord s z).
+
+Definition valueToZ (v : value) : Z :=
+ wordToZ (vword v).
+
+Definition uvalueToZ (v : value) : Z :=
+ uwordToZ (vword v).
+
+Definition intToValue (i : Integers.int) : value :=
+ ZToValue Int.wordsize (Int.unsigned i).
+
+(** 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 :=
+ negb (weqb (@wzero (vsize v)) (vword v)).
+
+Definition boolToValue (sz : nat) (b : bool) : value :=
+ natToValue sz (if b then 1 else 0).
+
+(** ** Arithmetic operations *)
+
+Lemma unify_word (sz1 sz2 : nat) (w1 : word sz2): sz1 = sz2 -> word sz1.
+Proof. intros; subst; assumption. Qed.
+
+Definition value_eq_size:
+ forall v1 v2 : value, { vsize v1 = vsize v2 } + { True }.
+Proof.
+ intros; destruct (Nat.eqb (vsize v1) (vsize v2)) eqn:?.
+ left; apply Nat.eqb_eq in Heqb; assumption.
+ right; trivial.
+Defined.
+
+Definition value_eq_size_nat:
+ forall (sz : nat) (v : value), { sz = vsize v } + { True }.
+Proof.
+ intros; destruct (Nat.eqb sz (vsize v)) eqn:?.
+ left; apply Nat.eqb_eq in Heqb; assumption.
+ right; trivial.
+Defined.
+
+Definition map_any {A : Type} (v1 v2 : value) (f : word (vsize v1) -> word (vsize v1) -> A)
+ (EQ : vsize v1 = vsize v2) : A :=
+ let w2 := unify_word (vsize v1) (vsize v2) (vword v2) EQ in
+ f (vword v1) w2.
+
+Definition map_any_opt {A : Type} (sz : nat) (v1 v2 : value) (f : word (vsize v1) -> word (vsize v1) -> A)
+ : option A :=
+ match value_eq_size v1 v2 with
+ | left EQ =>
+ Some (map_any v1 v2 f EQ)
+ | _ => None
+ end.
+
+Definition map_word (f : forall sz : nat, word sz -> word sz) (v : value) : value :=
+ mkvalue (vsize v) (f (vsize v) (vword v)).
+
+Definition map_word2 (f : forall sz : nat, word sz -> word sz -> word sz) (v1 v2 : value)
+ (EQ : (vsize v1 = vsize v2)) : value :=
+ let w2 := unify_word (vsize v1) (vsize v2) (vword v2) EQ in
+ mkvalue (vsize v1) (f (vsize v1) (vword v1) w2).
+
+Definition map_word2_opt (f : forall sz : nat, word sz -> word sz -> word sz) (v1 v2 : value)
+ : option value :=
+ match value_eq_size v1 v2 with
+ | left EQ => Some (map_word2 f v1 v2 EQ)
+ | _ => None
+ end.
+
+Definition eq_to_opt (v1 v2 : value) (f : vsize v1 = vsize v2 -> value)
+ : option value :=
+ match value_eq_size v1 v2 with
+ | left EQ => Some (f EQ)
+ | _ => None
+ end.
+
+(** Arithmetic operations over [value], interpreting them as signed or unsigned
+depending on the operation.
+
+The arithmetic operations over [word] are over [N] by default, however, can also
+be called over [Z] explicitly, which is where the bits are interpreted in a
+signed manner. *)
+
+Definition vplus v1 v2 := map_word2 wplus v1 v2.
+Definition vminus v1 v2 := map_word2 wminus v1 v2.
+Definition vmul v1 v2 := map_word2 wmult v1 v2.
+Definition vdiv v1 v2 := map_word2 wdiv v1 v2.
+Definition vmod v1 v2 := map_word2 wmod v1 v2.
+
+Definition vmuls v1 v2 := map_word2 wmultZ v1 v2.
+Definition vdivs v1 v2 := map_word2 wdivZ v1 v2.
+Definition vmods v1 v2 := map_word2 wremZ v1 v2.
+
+(** ** Bitwise operations
+
+Bitwise operations over [value], which is independent of whether the number is
+signed or unsigned. *)
+
+Definition vnot v := map_word wnot v.
+Definition vneg v := map_word wneg v.
+Definition vbitneg v := boolToValue (vsize v) (negb (valueToBool v)).
+Definition vor v1 v2 := map_word2 wor v1 v2.
+Definition vand v1 v2 := map_word2 wand v1 v2.
+Definition vxor v1 v2 := map_word2 wxor v1 v2.
+
+(** ** Comparison operators
+
+Comparison operators that return a bool, there should probably be an equivalent
+which returns another number, however I might just add that as an explicit
+conversion. *)
+
+Definition veqb v1 v2 := map_any v1 v2 (@weqb (vsize v1)).
+Definition vneb v1 v2 EQ := negb (veqb v1 v2 EQ).
+
+Definition veq v1 v2 EQ := boolToValue (vsize v1) (veqb v1 v2 EQ).
+Definition vne v1 v2 EQ := boolToValue (vsize v1) (vneb v1 v2 EQ).
+
+Definition vltb v1 v2 := map_any v1 v2 wltb.
+Definition vleb v1 v2 EQ := negb (map_any v2 v1 wltb (eq_sym EQ)).
+Definition vgtb v1 v2 EQ := map_any v2 v1 wltb (eq_sym EQ).
+Definition vgeb v1 v2 EQ := negb (map_any v1 v2 wltb EQ).
+
+Definition vltsb v1 v2 := map_any v1 v2 wsltb.
+Definition vlesb v1 v2 EQ := negb (map_any v2 v1 wsltb (eq_sym EQ)).
+Definition vgtsb v1 v2 EQ := map_any v2 v1 wsltb (eq_sym EQ).
+Definition vgesb v1 v2 EQ := negb (map_any v1 v2 wsltb EQ).
+
+Definition vlt v1 v2 EQ := boolToValue (vsize v1) (vltb v1 v2 EQ).
+Definition vle v1 v2 EQ := boolToValue (vsize v1) (vleb v1 v2 EQ).
+Definition vgt v1 v2 EQ := boolToValue (vsize v1) (vgtb v1 v2 EQ).
+Definition vge v1 v2 EQ := boolToValue (vsize v1) (vgeb v1 v2 EQ).
+
+Definition vlts v1 v2 EQ := boolToValue (vsize v1) (vltsb v1 v2 EQ).
+Definition vles v1 v2 EQ := boolToValue (vsize v1) (vlesb v1 v2 EQ).
+Definition vgts v1 v2 EQ := boolToValue (vsize v1) (vgtsb v1 v2 EQ).
+Definition vges v1 v2 EQ := boolToValue (vsize v1) (vgesb v1 v2 EQ).
+
+(** ** Shift operators
+
+Shift operators on values. *)
+
+Definition shift_map (sz : nat) (f : word sz -> nat -> word sz) (w1 w2 : word sz) :=
+ f w1 (wordToNat w2).
+
+Definition vshl v1 v2 := map_word2 (fun sz => shift_map sz (@wlshift sz)) v1 v2.
+Definition vshr v1 v2 := map_word2 (fun sz => shift_map sz (@wrshift sz)) v1 v2.
diff --git a/src/verilog/Verilog.v b/src/verilog/Verilog.v
index b9200b7..61df580 100644
--- a/src/verilog/Verilog.v
+++ b/src/verilog/Verilog.v
@@ -1,4 +1,4 @@
-(*
+(* -*- mode: coq -*-
* CoqUp: Verified high-level synthesis.
* Copyright (C) 2019-2020 Yann Herklotz <yann@yannherklotz.com>
*
@@ -21,38 +21,44 @@ From Coq Require Import
FSets.FMapPositive
Program.Basics
PeanoNat
- ZArith.
+ ZArith
+ Lists.List
+ Program.
-From bbv Require Word.
+Import ListNotations.
-From coqup.common Require Import Coquplib Show.
+From coqup Require Import common.Coquplib common.Show verilog.Value.
From compcert Require Integers.
+From compcert Require Import Errors.
-Import ListNotations.
+Notation "a ! b" := (PositiveMap.find b a) (at level 1).
Definition reg : Type := positive.
+Definition node : Type := positive.
Definition szreg : Type := reg * nat.
-Record value : Type := mkvalue {
- vsize : nat;
- vword : Word.word vsize
-}.
+Definition assoclist : Type := PositiveMap.t value.
-Definition posToValue (p : positive) : value :=
- let size := Z.to_nat (Z.succ (log_inf p)) in
- mkvalue size (Word.posToWord size p).
+(** * Verilog AST
-Definition ZToValue (s : nat) (z : Z) : value :=
- mkvalue s (Word.ZToWord s z).
+The Verilog AST is defined here, which is the target language of the
+compilation.
-Definition intToValue (i : Integers.int) : value :=
- mkvalue 32%nat (Word.ZToWord 32%nat (Integers.Int.unsigned i)).
+** Value
-Definition valueToZ (v : value) : Z :=
- Word.uwordToZ v.(vword).
+The Verilog [value] is a bitvector containg a size and the actual bitvector. In
+this case, the [Word.word] type is used as many theorems about that bitvector
+have already been proven. *)
-Definition state : Type := PositiveMap.t value * PositiveMap.t value.
+Definition estate : Type := assoclist * assoclist.
+
+(** ** Binary Operators
+
+These are the binary operations that can be represented in Verilog. Ideally,
+multiplication and division would be done by custom modules which could al so be
+scheduled properly. However, for now every Verilog operator is assumed to take
+one clock cycle. *)
Inductive binop : Type :=
| Vadd : binop (** addition (binary [+]) *)
@@ -61,7 +67,7 @@ Inductive binop : Type :=
| Vdiv : binop (** division (binary [/]) *)
| Vdivu : binop (** division unsigned (binary [/]) *)
| Vmod : binop (** remainder ([%]) *)
-| Vmodu : binop (** remainder unsigned ([/]) *)
+| Vmodu : binop (** remainder unsigned ([%]) *)
| Vlt : binop (** less than ([<]) *)
| Vltu : binop (** less than unsigned ([<]) *)
| Vgt : binop (** greater than ([>]) *)
@@ -76,49 +82,75 @@ Inductive binop : Type :=
| Vor : binop (** or (binary [|]) *)
| Vxor : binop (** xor (binary [^|]) *)
| Vshl : binop (** shift left ([<<]) *)
-| Vshr : binop. (** shift left ([<<]) *)
+| Vshr : binop. (** shift right ([>>]) *)
+
+(** ** Unary Operators *)
Inductive unop : Type :=
| Vneg (** negation ([~]) *)
| Vnot. (** not operation [!] *)
+(** ** Expressions *)
+
Inductive expr : Type :=
| Vlit : value -> expr
| Vvar : reg -> expr
+| Vinputvar : reg -> expr
| Vbinop : binop -> expr -> expr -> expr
| Vunop : unop -> expr -> expr
| Vternary : expr -> expr -> expr -> expr.
-Definition posToExpr (p : positive) : expr :=
- Vlit (posToValue p).
+Definition posToExpr (sz : nat) (p : positive) : expr :=
+ Vlit (posToValue sz p).
+
+(** ** Statements *)
Inductive stmnt : Type :=
| Vskip : stmnt
-| Vseq : list stmnt -> stmnt
+| Vseq : stmnt -> stmnt -> stmnt
| Vcond : expr -> stmnt -> stmnt -> stmnt
-| Vcase : expr -> list (expr * stmnt) -> stmnt
+| Vcase : expr -> list (expr * stmnt) -> option stmnt -> stmnt
| Vblock : expr -> expr -> stmnt
| Vnonblock : expr -> expr -> stmnt.
-(** [edge] is not part of [stmnt] in this formalisation because is closer to the
- semantics that are used. *)
+(** ** Edges
+
+These define when an always block should be triggered, for example if the always
+block should be triggered synchronously at the clock edge, or asynchronously for
+combinational logic.
+
+[edge] is not part of [stmnt] in this formalisation because is closer to the
+semantics that are used. *)
+
Inductive edge : Type :=
| Vposedge : reg -> edge
| Vnegedge : reg -> edge
| Valledge : edge
| Voredge : edge -> edge -> edge.
+(** ** Module Items
+
+Module items can either be declarations ([Vdecl]) or always blocks ([Valways]).
+The declarations are always register declarations as combinational logic can be
+done using combinational always block instead of continuous assignments. *)
+
Inductive module_item : Type :=
| Vdecl : reg -> nat -> module_item
-| Valways : edge -> stmnt -> module_item.
-
-(** [mod_start] If set, starts the computations in the module. *)
-(** [mod_reset] If set, reset the state in the module. *)
-(** [mod_clk] The clock that controls the computation in the module. *)
-(** [mod_args] The arguments to the module. *)
-(** [mod_finish] Bit that is set if the result is ready. *)
-(** [mod_return] The return value that was computed. *)
-(** [mod_body] The body of the module, including the state machine. *)
+| Valways : edge -> stmnt -> module_item
+| Valways_ff : edge -> stmnt -> module_item
+| Valways_comb : edge -> stmnt -> module_item.
+
+(** The main module type containing all the important control signals
+
+- [mod_start] If set, starts the computations in the module.
+- [mod_reset] If set, reset the state in the module.
+- [mod_clk] The clock that controls the computation in the module.
+- [mod_args] The arguments to the module.
+- [mod_finish] Bit that is set if the result is ready.
+- [mod_return] The return value that was computed.
+- [mod_body] The body of the module, including the state machine.
+*)
+
Record module : Type := mkmodule {
mod_start : szreg;
mod_reset : szreg;
@@ -132,7 +164,296 @@ Record module : Type := mkmodule {
(** Convert a [positive] to an expression directly, setting it to the right
size. *)
Definition posToLit (p : positive) : expr :=
- Vlit (posToValue p).
+ Vlit (posToValueAuto p).
Coercion Vlit : value >-> expr.
Coercion Vvar : reg >-> expr.
+
+Inductive state: Type :=
+| State:
+ forall (assoc: assoclist)
+ (nbassoc: assoclist),
+ state
+| Callstate: state
+| Returnstate: state.
+
+Definition fext := reg -> res value.
+Definition fextclk := nat -> fext.
+
+Definition binop_run (op : binop) : forall v1 v2 : value, vsize v1 = vsize v2 -> 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
+ end.
+
+Definition unop_run (op : unop) : value -> value :=
+ match op with
+ | Vneg => vnot
+ | Vnot => vbitneg
+ end.
+
+Inductive expr_runp : assoclist -> expr -> value -> Prop :=
+ | erun_Vlit :
+ forall a v,
+ expr_runp a (Vlit v) v
+ | erun_Vvar :
+ forall assoc v r,
+ assoc!r = Some v ->
+ expr_runp assoc (Vvar r) v
+ | erun_Vbinop :
+ forall a op l r lv rv oper EQ,
+ expr_runp a l lv ->
+ expr_runp a r rv ->
+ oper = binop_run op ->
+ expr_runp a (Vbinop op l r) (oper lv rv EQ)
+ | erun_Vunop :
+ forall a u vu op oper,
+ expr_runp a u vu ->
+ oper = unop_run op ->
+ expr_runp a (Vunop op u) (oper vu)
+ | erun_Vternary_true :
+ forall a c t f vc vt,
+ expr_runp a c vc ->
+ expr_runp a t vt ->
+ valueToBool vc = true ->
+ expr_runp a (Vternary c t f) vt
+ | erun_Vternary_false :
+ forall a c t f vc vf,
+ expr_runp a c vc ->
+ expr_runp a f vf ->
+ valueToBool vc = false ->
+ expr_runp a (Vternary c t f) vf.
+
+Definition handle_opt {A : Type} (err : errmsg) (val : option A)
+ : res A :=
+ match val with
+ | Some a => OK a
+ | None => Error err
+ end.
+
+Definition handle_def {A : Type} (a : A) (val : option A)
+ : res A :=
+ match val with
+ | Some a' => OK a'
+ | None => OK a
+ end.
+
+Local Open Scope error_monad_scope.
+
+(* TODO FIX Vvar case without default *)
+Fixpoint expr_run (f : fext) (assoc : assoclist) (e : expr)
+ {struct e} : res value :=
+ match e with
+ | Vlit v => OK v
+ | Vvar r => handle_def (ZToValue 32 0) assoc!r
+ | Vinputvar r => f r
+ | Vbinop op l r =>
+ let lv := expr_run f assoc l in
+ let rv := expr_run f assoc r in
+ let oper := binop_run op in
+ do lv' <- lv;
+ do rv' <- rv;
+ handle_opt (msg "Verilog: sizes are not equal")
+ (eq_to_opt lv' rv' (oper lv' rv'))
+ | Vunop op e =>
+ let oper := unop_run op in
+ do ev <- expr_run f assoc e;
+ OK (oper ev)
+ | Vternary c te fe =>
+ do cv <- expr_run f assoc c;
+ if valueToBool cv then expr_run f assoc te else expr_run f assoc fe
+ end.
+
+(** Return the name of the lhs of an assignment. For now, this function is quite
+simple because only assignment to normal variables is supported and needed. *)
+
+Definition assign_name (e : expr) : res reg :=
+ match e with
+ | Vvar r => OK r
+ | _ => Error (msg "Verilog: expression not supported on lhs of assignment")
+ end.
+
+Fixpoint find_case_stmnt (f : fext) (a : assoclist) (v : value) (cl : list (expr * stmnt))
+ {struct cl} : option (res stmnt) :=
+ match cl with
+ | (e, s)::xs =>
+ match expr_run f a e with
+ | OK v' =>
+ match eq_to_opt v v' (veq v v') with
+ | Some eq => if valueToBool eq then Some (OK s) else find_case_stmnt f a v xs
+ | None => Some (Error (msg "Verilog: equality check sizes not equal"))
+ end
+ | Error msg => Some (Error msg)
+ end
+ | _ => None
+ end.
+
+Fixpoint stmnt_run' (f : fext) (n : nat) (s : state) (st : stmnt) {struct n} : res state :=
+ match n with
+ | S n' =>
+ match st with
+ | Vskip => OK s
+ | Vseq s1 s2 =>
+ do s' <- stmnt_run' f n' s s1;
+ stmnt_run' f n' s' s2
+ | Vcond c st sf =>
+ match s with
+ | State assoc _ =>
+ do cv <- expr_run f assoc c;
+ if valueToBool cv
+ then stmnt_run' f n' s st
+ else stmnt_run' f n' s sf
+ | _ => Error (msg "Verilog: stmnt execution in wrong state")
+ end
+ | Vcase e cl defst =>
+ match s with
+ | State a _ =>
+ do v <- expr_run f a e;
+ match find_case_stmnt f a v cl with
+ | Some (OK st') => stmnt_run' f n' s st'
+ | Some (Error msg) => Error msg
+ | None => do s' <- handle_opt (msg "Verilog: no case was matched")
+ (option_map (stmnt_run' f n' s) defst); s'
+ end
+ | _ => Error (msg "Verilog: stmnt execution in wrong state")
+ end
+ | Vblock lhs rhs =>
+ match s with
+ | State assoc nbassoc =>
+ do name <- assign_name lhs;
+ do rhse <- expr_run f assoc rhs;
+ OK (State (PositiveMap.add name rhse assoc) nbassoc)
+ | _ => Error (msg "Verilog: stmnt exectution in wrong state")
+ end
+ | Vnonblock lhs rhs =>
+ match s with
+ | State assoc nbassoc =>
+ do name <- assign_name lhs;
+ do rhse <- expr_run f assoc rhs;
+ OK (State assoc (PositiveMap.add name rhse nbassoc))
+ | _ => Error (msg "Verilog: stmnt execution in wrong state")
+ end
+ end
+ | _ => OK s
+ end.
+
+Fixpoint stmnt_height (st : stmnt) {struct st} : nat :=
+ match st with
+ | Vskip => 1
+ | Vseq s1 s2 => stmnt_height s1 + stmnt_height s2
+ | Vcond _ s1 s2 => Nat.max (stmnt_height s1) (stmnt_height s2)
+ | Vcase _ ls (Some st) =>
+ fold_right (fun t acc => Nat.max acc (stmnt_height (snd t))) 0%nat ls
+ | _ => 1
+ end.
+
+Definition stmnt_run (f : fext) (s : state) (st : stmnt) : res state :=
+ stmnt_run' f (stmnt_height st) s st.
+
+Fixpoint mi_step (f : fext) (s : state) (m : list module_item) {struct m} : res state :=
+ let run := fun st ls =>
+ do s' <- stmnt_run f s st;
+ mi_step f s' ls
+ in
+ match m with
+ | (Valways _ st)::ls => run st ls
+ | (Valways_ff _ st)::ls => run st ls
+ | (Valways_comb _ st)::ls => run st ls
+ | (Vdecl _ _)::ls => mi_step f s ls
+ | nil => OK s
+ end.
+
+Definition add_assoclist (r : reg) (v : value) (assoc : assoclist) : assoclist :=
+ PositiveMap.add r v assoc.
+
+Definition merge_assoclist (nbassoc assoc : assoclist) : assoclist :=
+ PositiveMap.fold add_assoclist nbassoc assoc.
+
+Definition empty_assoclist : assoclist := PositiveMap.empty value.
+
+Definition mi_step_commit (f : fext) (assoc : assoclist) (m : list module_item) : res assoclist :=
+ match mi_step f (State assoc empty_assoclist) m with
+ | OK (State assoc' nbassoc) =>
+ OK (merge_assoclist nbassoc assoc')
+ | Error msg => Error msg
+ | _ => Error (msg "Returned in the wrong state")
+ end.
+
+Fixpoint mi_run (f : fextclk) (assoc : assoclist) (m : list module_item) (n : nat)
+ {struct n} : res assoclist :=
+ match n with
+ | S n' =>
+ do assoc' <- mi_step_commit (f n') assoc m;
+ mi_run f assoc' m n'
+ | O => OK assoc
+ end.
+
+Definition module_run (n : nat) (m : module) : res assoclist :=
+ let f :=
+ fun n =>
+ match n with
+ | 1%nat => fun r => if Pos.eqb r (fst (mod_reset m)) then OK (natToValue 1 1) else Error (msg "")
+ | _ => fun r => if Pos.eqb r (fst (mod_reset m)) then OK (natToValue 1 0) else Error (msg "")
+ end in
+ mi_run f empty_assoclist (mod_body m) n.
+
+Local Close Scope error_monad_scope.
+
+(*Theorem value_eq_size_if_eq:
+ forall lv rv EQ,
+ vsize lv = vsize rv -> value_eq_size lv rv = left EQ.
+Proof. intros. unfold value_eq_size.
+
+Theorem expr_run_same:
+ forall assoc e v, expr_run assoc e = OK v <-> expr_runp assoc e v.
+Proof.
+ split; generalize dependent v; generalize dependent assoc.
+ - induction e.
+ + intros. inversion H. constructor.
+ + intros. inversion H. constructor. assumption.
+ + intros. inversion H. destruct (expr_run assoc e1) eqn:?. destruct (expr_run assoc e2) eqn:?.
+ unfold eq_to_opt in H1. destruct (value_eq_size v0 v1) eqn:?. inversion H1.
+ constructor. apply IHe1. assumption. apply IHe2. assumption. reflexivity. discriminate. discriminate.
+ discriminate.
+ + intros. inversion H. destruct (expr_run assoc e) eqn:?. unfold option_map in H1.
+ inversion H1. constructor. apply IHe. assumption. reflexivity. discriminate.
+ + intros. inversion H. destruct (expr_run assoc e1) eqn:?. destruct (valueToBool v0) eqn:?.
+ eapply erun_Vternary_true. apply IHe1. eassumption. apply IHe2. eassumption. assumption.
+ eapply erun_Vternary_false. apply IHe1. eassumption. apply IHe3. eassumption. assumption.
+ discriminate.
+ - induction e.
+ + intros. inversion H. reflexivity.
+ + intros. inversion H. subst. simpl. assumption.
+ + intros. inversion H. subst. simpl. apply IHe1 in H4. rewrite H4.
+ apply IHe2 in H6. rewrite H6. unfold eq_to_opt. assert (vsize lv = vsize rv).
+ apply EQ. apply (value_eq_size_if_eq lv rv EQ) in H0. rewrite H0. reflexivity.
+ + intros. inversion H. subst. simpl. destruct (expr_run assoc e) eqn:?. simpl.
+ apply IHe in H3. rewrite Heqo in H3.
+ inversion H3. subst. reflexivity. apply IHe in H3. rewrite Heqo in H3. discriminate.
+ + intros. inversion H. subst. simpl. apply IHe1 in H4. rewrite H4. rewrite H7.
+ apply IHe2 in H6. rewrite H6. reflexivity.
+ subst. simpl. apply IHe1 in H4. rewrite H4. rewrite H7. apply IHe3.
+ assumption.
+Qed.
+
+*)