diff options
Diffstat (limited to 'src/verilog/Verilog.v')
-rw-r--r-- | src/verilog/Verilog.v | 335 |
1 files changed, 247 insertions, 88 deletions
diff --git a/src/verilog/Verilog.v b/src/verilog/Verilog.v index dfb6255..e2b85b2 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> * @@ -27,18 +27,22 @@ From Coq Require Import Import ListNotations. -From coqup Require Import common.Coquplib common.Show verilog.Value. +From coqup Require Import common.Coquplib common.Show verilog.Value AssocMap. +From compcert Require Integers Events. +From compcert Require Import Errors Smallstep Globalenvs. -From compcert Require Integers. -From compcert Require Import Errors. - -Notation "a ! b" := (PositiveMap.find b a) (at level 1). +Import HexNotationValue. +Import AssocMapNotation. Definition reg : Type := positive. Definition node : Type := positive. Definition szreg : Type := reg * nat. -Definition assoclist : Type := PositiveMap.t value. +Record associations : Type := + mkassociations { + assoc_blocking : assocmap; + assoc_nonblocking : assocmap + }. (** * Verilog AST @@ -51,8 +55,6 @@ 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 estate : Type := assoclist * assoclist. - (** ** Binary Operators These are the binary operations that can be represented in Verilog. Ideally, @@ -159,10 +161,10 @@ Record module : Type := mkmodule { mod_clk : szreg; mod_finish : szreg; mod_return : szreg; + mod_state : szreg; (**r Variable that defines the current state, it should be internal. *) mod_args : list szreg; mod_body : list module_item; -}. - + }. (** Convert a [positive] to an expression directly, setting it to the right size. *) Definition posToLit (p : positive) : expr := @@ -171,15 +173,41 @@ Definition posToLit (p : positive) : expr := Coercion Vlit : value >-> expr. Coercion Vvar : reg >-> expr. -Definition fext := PositiveMap.t value. +Definition fext := AssocMap.t value. Definition fextclk := nat -> fext. -Inductive state: Type := - State: - forall (assoc : assoclist) - (nbassoc : assoclist) +(** ** State + +The [state] contains the following items: +n +- Current [module] that is being worked on, so that the state variable can be +retrieved and set appropriately. +- Current [module_item] which is being worked on. +- A contiunation ([cont]) which defines what to do next. The option is to + either evaluate another module item or go to the next clock cycle. Finally + it could also end if the finish flag of the module goes high. +- Association list containing the blocking assignments made, or assignments made + in previous clock cycles. +- Nonblocking association list containing all the nonblocking assignments made + in the current module. +- The environment containing values for the input. +- The program counter which determines the value for the state in this version of + Verilog, as the Verilog was generated by the RTL, which means that we have to + make an assumption about how it looks. In this case, that it contains state + which determines which part of the Verilog is executed. This is then the part + of the Verilog that should match with the RTL. *) + +Inductive state : Type := +| State: + forall (m : module) + (assoc : assocmap) + (nbassoc : assocmap) (f : fextclk) - (cycle : positive), + (cycle : nat) + (stvar : value), + state +| Finishstate: + forall v : value, state. Definition binop_run (op : binop) : forall v1 v2 : value, vsize v1 = vsize v2 -> value := @@ -214,40 +242,48 @@ Definition unop_run (op : unop) : value -> value := | Vnot => vbitneg end. -Inductive expr_runp : state -> expr -> value -> Prop := +Inductive expr_runp : fext -> assocmap -> expr -> value -> Prop := | erun_Vlit : - forall s v, - expr_runp s (Vlit v) v + forall fext assoc v, + expr_runp fext assoc (Vlit v) v | erun_Vvar : - forall assoc na f c v r, + forall fext assoc v r, assoc!r = Some v -> - expr_runp (State assoc na f c) (Vvar r) v + expr_runp fext assoc (Vvar r) v + | erun_Vvar_empty : + forall fext assoc r sz, + assoc!r = None -> + expr_runp fext assoc (Vvar r) (ZToValue sz 0) | erun_Vinputvar : - forall s r v, - expr_runp s (Vinputvar r) v + forall fext assoc r v, + fext!r = Some v -> + expr_runp fext assoc (Vinputvar r) v | erun_Vbinop : - forall s op l r lv rv oper EQ, - expr_runp s l lv -> - expr_runp s r rv -> + forall fext assoc op l r lv rv oper EQ resv, + expr_runp fext assoc l lv -> + expr_runp fext assoc r rv -> oper = binop_run op -> - expr_runp s (Vbinop op l r) (oper lv rv EQ) + resv = oper lv rv EQ -> + expr_runp fext assoc (Vbinop op l r) resv | erun_Vunop : - forall s u vu op oper, - expr_runp s u vu -> + forall fext assoc u vu op oper resv, + expr_runp fext assoc u vu -> oper = unop_run op -> - expr_runp s (Vunop op u) (oper vu) + resv = oper vu -> + expr_runp fext assoc (Vunop op u) resv | erun_Vternary_true : - forall s c ts fs vc vt, - expr_runp s c vc -> - expr_runp s ts vt -> + forall fext assoc c ts fs vc vt, + expr_runp fext assoc c vc -> + expr_runp fext assoc ts vt -> valueToBool vc = true -> - expr_runp s (Vternary c ts fs) vt + expr_runp fext assoc (Vternary c ts fs) vt | erun_Vternary_false : - forall s c ts fs vc vf, - expr_runp s c vc -> - expr_runp s fs vf -> + forall fext assoc c ts fs vc vf, + expr_runp fext assoc c vc -> + expr_runp fext assoc fs vf -> valueToBool vc = false -> - expr_runp s (Vternary c ts fs) vf. + expr_runp fext assoc (Vternary c ts fs) vf. +Hint Constructors expr_runp : verilog. Definition handle_opt {A : Type} (err : errmsg) (val : option A) : res A := @@ -265,22 +301,20 @@ Definition handle_def {A : Type} (a : A) (val : option A) Local Open Scope error_monad_scope. -Definition access_fext (s : state) (r : reg) : res value := - match s with - | State _ _ f c => - match PositiveMap.find r (f (Pos.to_nat c)) with - | Some v => OK v - | _ => OK (ZToValue 1 0) - end +Definition access_fext (f : fext) (r : reg) : res value := + match AssocMap.get r f with + | Some v => OK v + | _ => OK (ZToValue 1 0) end. (* TODO FIX Vvar case without default *) -Fixpoint expr_run (s : state) (e : expr) +(*Fixpoint expr_run (assoc : assocmap) (e : expr) {struct e} : res value := match e with | Vlit v => OK v | Vvar r => match s with - | State assoc _ _ _ => handle_def (ZToValue 32 0) assoc!r + | State _ assoc _ _ _ => handle_def (ZToValue 32 0) assoc!r + | _ => Error (msg "Verilog: Wrong state") end | Vvari _ _ => Error (msg "Verilog: variable indexing not modelled") | Vinputvar r => access_fext s r @@ -299,7 +333,7 @@ Fixpoint expr_run (s : state) (e : expr) | Vternary c te fe => do cv <- expr_run s c; if valueToBool cv then expr_run s te else expr_run s fe - end. + 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. *) @@ -310,6 +344,15 @@ Definition assign_name (e : expr) : res reg := | _ => Error (msg "Verilog: expression not supported on lhs of assignment") end. +(*Fixpoint stmnt_height (st : stmnt) {struct st} : nat := + match st with + | Vseq s1 s2 => S (stmnt_height s1 + stmnt_height s2) + | Vcond _ s1 s2 => S (Nat.max (stmnt_height s1) (stmnt_height s2)) + | Vcase _ ls (Some st) => + S (fold_right (fun t acc => Nat.max acc (stmnt_height (snd t))) 0%nat ls) + | _ => 1 + end. + Fixpoint find_case_stmnt (s : state) (v : value) (cl : list (expr * stmnt)) {struct cl} : option (res stmnt) := match cl with @@ -348,35 +391,85 @@ Fixpoint stmnt_run' (n : nat) (s : state) (st : stmnt) {struct n} : res state := end | Vblock lhs rhs => match s with - | State assoc nbassoc f c => + | State m assoc nbassoc f c => do name <- assign_name lhs; do rhse <- expr_run s rhs; - OK (State (PositiveMap.add name rhse assoc) nbassoc f c) + OK (State m (PositiveMap.add name rhse assoc) nbassoc f c) + | _ => Error (msg "Verilog: Wrong state") end | Vnonblock lhs rhs => match s with - | State assoc nbassoc f c => + | State m assoc nbassoc f c => do name <- assign_name lhs; do rhse <- expr_run s rhs; - OK (State assoc (PositiveMap.add name rhse nbassoc) f c) + OK (State m assoc (PositiveMap.add name rhse nbassoc) f c) + | _ => Error (msg "Verilog: Wrong state") end end | _ => OK s end. -Fixpoint stmnt_height (st : stmnt) {struct st} : nat := - match st with - | Vseq s1 s2 => S (stmnt_height s1 + stmnt_height s2) - | Vcond _ s1 s2 => S (Nat.max (stmnt_height s1) (stmnt_height s2)) - | Vcase _ ls (Some st) => - S (fold_right (fun t acc => Nat.max acc (stmnt_height (snd t))) 0%nat ls) - | _ => 1 - end. - Definition stmnt_run (s : state) (st : stmnt) : res state := - stmnt_run' (stmnt_height st) s st. - -Fixpoint mi_step (s : state) (m : list module_item) {struct m} : res state := + stmnt_run' (stmnt_height st) s st. *) + +Inductive stmnt_runp: fext -> associations -> stmnt -> associations -> Prop := +| stmnt_runp_Vskip: + forall f a, stmnt_runp f a Vskip a +| stmnt_runp_Vseq: + forall f st1 st2 as0 as1 as2, + stmnt_runp f as0 st1 as1 -> + stmnt_runp f as1 st2 as2 -> + stmnt_runp f as0 (Vseq st1 st2) as2 +| stmnt_runp_Vcond_true: + forall as0 as1 f c vc stt stf, + expr_runp f as0.(assoc_blocking) c vc -> + valueToBool vc = true -> + stmnt_runp f as0 stt as1 -> + stmnt_runp f as0 (Vcond c stt stf) as1 +| stmnt_runp_Vcond_false: + forall as0 as1 f c vc stt stf, + expr_runp f as0.(assoc_blocking) c vc -> + valueToBool vc = false -> + stmnt_runp f as0 stf as1 -> + stmnt_runp f as0 (Vcond c stt stf) as1 +| stmnt_runp_Vcase_nomatch: + forall e ve as0 f as1 me mve sc cs def, + expr_runp f as0.(assoc_blocking) e ve -> + expr_runp f as0.(assoc_blocking) me mve -> + mve <> ve -> + stmnt_runp f as0 (Vcase e cs def) as1 -> + stmnt_runp f as0 (Vcase e ((me, sc)::cs) def) as1 +| stmnt_runp_Vcase_match: + forall e ve as0 f as1 me mve sc cs def, + expr_runp f as0.(assoc_blocking) e ve -> + expr_runp f as0.(assoc_blocking) me mve -> + mve = ve -> + stmnt_runp f as0 sc as1 -> + stmnt_runp f as0 (Vcase e ((me, sc)::cs) def) as1 +| stmnt_runp_Vcase_default: + forall as0 as1 f st e ve, + expr_runp f as0.(assoc_blocking) e ve -> + stmnt_runp f as0 st as1 -> + stmnt_runp f as0 (Vcase e nil (Some st)) as1 +| stmnt_runp_Vblock: + forall lhs name rhs rhsval assoc assoc' nbassoc f, + assign_name lhs = OK name -> + expr_runp f assoc rhs rhsval -> + assoc' = (AssocMap.set name rhsval assoc) -> + stmnt_runp f (mkassociations assoc nbassoc) + (Vblock lhs rhs) + (mkassociations assoc' nbassoc) +| stmnt_runp_Vnonblock: + forall lhs name rhs rhsval assoc nbassoc nbassoc' f, + assign_name lhs = OK name -> + expr_runp f assoc rhs rhsval -> + nbassoc' = (AssocMap.set name rhsval nbassoc) -> + stmnt_runp f (mkassociations assoc nbassoc) + (Vnonblock lhs rhs) + (mkassociations assoc nbassoc'). +Hint Constructors stmnt_runp : verilog. + +(*Fixpoint mi_step (s : state) (m : list module_item) {struct m} : res state := let run := fun st ls => do s' <- stmnt_run s st; mi_step s' ls @@ -388,41 +481,69 @@ Fixpoint mi_step (s : state) (m : list module_item) {struct m} : res state := | (Vdecl _ _)::ls => mi_step s ls | (Vdeclarr _ _ _)::ls => mi_step 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 (s : state) (m : list module_item) : res state := + end.*) + +Inductive mi_stepp : fext -> associations -> module_item -> associations -> Prop := +| mi_stepp_Valways : + forall f s0 st s1 c, + stmnt_runp f s0 st s1 -> + mi_stepp f s0 (Valways c st) s1 +| mi_stepp_Valways_ff : + forall f s0 st s1 c, + stmnt_runp f s0 st s1 -> + mi_stepp f s0 (Valways_ff c st) s1 +| mi_stepp_Valways_comb : + forall f s0 st s1 c, + stmnt_runp f s0 st s1 -> + mi_stepp f s0 (Valways_comb c st) s1 +| mi_stepp_Vdecl : + forall f s lhs rhs, + mi_stepp f s (Vdecl lhs rhs) s. +Hint Constructors mi_stepp : verilog. + +Inductive mis_stepp : fext -> associations -> list module_item -> associations -> Prop := +| mis_stepp_Cons : + forall f mi mis s0 s1 s2, + mi_stepp f s0 mi s1 -> + mis_stepp f s1 mis s2 -> + mis_stepp f s0 (mi :: mis) s2 +| mis_stepp_Nil : + forall f s, + mis_stepp f s nil s. +Hint Constructors mis_stepp : verilog. + +(*Definition mi_step_commit (s : state) (m : list module_item) : res state := match mi_step s m with - | OK (State assoc nbassoc f c) => - OK (State (merge_assoclist nbassoc assoc) empty_assoclist f c) + | OK (State m assoc nbassoc f c) => + OK (State m (merge_assocmap nbassoc assoc) empty_assocmap f c) | Error msg => Error msg + | _ => Error (msg "Verilog: Wrong state") end. -Fixpoint mi_run (f : fextclk) (assoc : assoclist) (m : list module_item) (n : nat) - {struct n} : res assoclist := +Fixpoint mi_run (f : fextclk) (assoc : assocmap) (m : list module_item) (n : nat) + {struct n} : res assocmap := match n with | S n' => do assoc' <- mi_run f assoc m n'; - match mi_step_commit (State assoc' empty_assoclist f (Pos.of_nat n')) m with + match mi_step_commit (State assoc' empty_assocmap f (Pos.of_nat n')) m with | OK (State assoc _ _ _) => OK assoc | Error m => Error m end | O => OK assoc - end. + end.*) -Definition module_run (n : nat) (m : module) : res assoclist := - let f := fun x => match x with - | S O => (add_assoclist (fst (mod_reset m)) (ZToValue 1 1) empty_assoclist) - | _ => (add_assoclist (fst (mod_reset m)) (ZToValue 1 0) empty_assoclist) - end in - mi_run f empty_assoclist (mod_body m) n. +(** Resets the module into a known state, so that it can be executed. This is +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 := + fun x => match x with + | S O => (AssocMap.set (fst (mod_reset m)) (ZToValue 1 1) empty_assocmap) + | _ => (AssocMap.set (fst (mod_reset m)) (ZToValue 1 0) empty_assocmap) + end. + +(*Definition module_run (n : nat) (m : module) : res assocmap := + mi_run (initial_fextclk m) empty_assocmap (mod_body m) n.*) Local Close Scope error_monad_scope. @@ -463,4 +584,42 @@ Proof. assumption. Qed. + *) + +Definition genv := Genv.t unit unit. + +Inductive step : state -> state -> Prop := +| step_module : + forall m stvar stvar' cycle f assoc0 assoc1 assoc2 nbassoc, + mis_stepp (f cycle) (mkassociations assoc0 empty_assocmap) + m.(mod_body) + (mkassociations assoc1 nbassoc) -> + assoc2 = merge_assocmap nbassoc assoc1 -> + Some stvar' = assoc2!(fst m.(mod_state)) -> + step (State m assoc0 empty_assocmap f cycle stvar) + (State m assoc2 empty_assocmap f (S cycle) stvar') +| step_finish : + forall m assoc f cycle stvar result, + assoc!(fst m.(mod_finish)) = Some (1'h"1") -> + assoc!(fst m.(mod_return)) = Some result -> + step (State m assoc empty_assocmap f cycle stvar) + (Finishstate result). +Hint Constructors step : verilog. + +(*Inductive initial_state (m: module): state -> Prop := +| initial_state_intro: + forall hmi tmi, + hmi::tmi = mod_body m -> + initial_state m (State m hmi tmi empty_assocmap empty_assocmap (initial_fextclk m) O xH). + +(** A final state is a [Returnstate] with an empty call stack. *) + +Inductive final_state: state -> Integers.int -> Prop := + | final_state_intro: forall v, + final_state (Finishstate v) (valueToInt v). + +(** The small-step semantics for a module. *) + +Definition semantics (p: module) := + Semantics step (initial_state p) final_state (Genv.empty_genv unit unit nil). *) |