summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sail.ml3
-rw-r--r--src/type_check.ml113
-rw-r--r--src/type_check.mli3
3 files changed, 102 insertions, 17 deletions
diff --git a/src/sail.ml b/src/sail.ml
index b355483d..85e36ce5 100644
--- a/src/sail.ml
+++ b/src/sail.ml
@@ -305,6 +305,9 @@ let options = Arg.align ([
( "-enum_casts",
Arg.Set Initial_check.opt_enum_casts,
" allow enumerations to be automatically casted to numeric range types");
+ ( "-new_bitfields",
+ Arg.Set Type_check.opt_new_bitfields,
+ " use new bitfield syntax");
( "-non_lexical_flow",
Arg.Set Nl_flow.opt_nl_flow,
" allow non-lexical flow typing");
diff --git a/src/type_check.ml b/src/type_check.ml
index ac0d8af2..7d4bbf07 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -79,6 +79,9 @@ let opt_smt_linearize = ref false
(* Allow use of div and mod when rewriting nexps *)
let opt_smt_div = ref false
+(* Use new bitfield syntax, more compatible with ASL *)
+let opt_new_bitfields = ref false
+
let depth = ref 0
let rec indent n = match n with
@@ -131,6 +134,7 @@ type env =
poly_undefineds : bool;
prove : (env -> n_constraint -> bool) option;
allow_unknowns : bool;
+ bitfields : (Big_int.num * Big_int.num) Bindings.t Bindings.t;
}
exception Type_error of env * l * type_error;;
@@ -469,6 +473,8 @@ module Env : sig
val base_typ_of : t -> typ -> typ
val allow_unknowns : t -> bool
val set_allow_unknowns : bool -> t -> t
+ val add_bitfield : id -> (Big_int.num * Big_int.num) Bindings.t -> t -> t
+ val get_bitfield_range : l -> id -> id -> t -> (Big_int.num * Big_int.num)
val no_bindings : t -> t
@@ -520,6 +526,7 @@ end = struct
poly_undefineds = false;
prove = None;
allow_unknowns = false;
+ bitfields = Bindings.empty;
}
let set_prover f env = { env with prove = f }
@@ -1162,7 +1169,7 @@ end = struct
match Bindings.find_opt id env.scattered_variant_envs with
| Some env' -> env'
| None -> typ_error env (id_loc id) ("scattered union " ^ string_of_id id ^ " has not been declared")
-
+
let is_register id env =
Bindings.mem id env.registers
@@ -1319,6 +1326,18 @@ end = struct
| targ -> rewrap targ in
aux (expand_synonyms env typ)
+ let get_bitfield_range l id field env =
+ match Bindings.find_opt id env.bitfields with
+ | Some ranges ->
+ begin match Bindings.find_opt field ranges with
+ | Some range -> range
+ | None -> typ_error env l (Printf.sprintf "Field %s does not exist in the bitfield %s" (string_of_id field) (string_of_id id))
+ end
+ | None -> typ_error env l (Printf.sprintf "%s is not a bitfield" (string_of_id id))
+
+ let add_bitfield id ranges env =
+ { env with bitfields = Bindings.add id ranges env.bitfields }
+
let allow_polymorphic_undefineds env =
{ env with poly_undefineds = true }
@@ -3674,7 +3693,16 @@ and infer_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) =
annot_lexp (LEXP_vector (inferred_v_lexp, inferred_exp)) bit_typ
else
typ_error env l ("Vector assignment not provably in bounds " ^ string_of_lexp lexp)
- | _ -> typ_error env l "Cannot assign vector element of non vector type"
+ | Typ_id id when !opt_new_bitfields ->
+ begin match exp with
+ | E_aux (E_id field, _) ->
+ let (hi, lo) = Env.get_bitfield_range l id field env in
+ let hi, lo = mk_exp ~loc:l (E_lit (L_aux (L_num hi, l))), mk_exp ~loc:l (E_lit (L_aux (L_num lo, l))) in
+ infer_lexp env (LEXP_aux (LEXP_vector_range (LEXP_aux (LEXP_field (v_lexp, Id_aux (Id "bits", l)), (l, ())), hi, lo), (l, ())))
+ | _ ->
+ typ_error env l (string_of_exp exp ^ " is not a bitfield accessor")
+ end
+ | _ -> typ_error env l "Cannot assign vector element of non vector or bitfield type"
end
| LEXP_vector_concat [] -> typ_error env l "Cannot have empty vector concatenation l-expression"
| LEXP_vector_concat (v_lexp :: v_lexps) ->
@@ -3893,7 +3921,25 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) =
annot_exp (E_if (cond', then_branch', else_branch')) (typ_of then_branch')
end
end
- | E_vector_access (v, n) -> infer_exp env (E_aux (E_app (mk_id "vector_access", [v; n]), (l, ())))
+ | E_vector_access (v, n) ->
+ begin
+ try infer_exp env (E_aux (E_app (mk_id "vector_access", [v; n]), (l, ()))) with
+ | Type_error (err_env, err_l, err) when !opt_new_bitfields ->
+ (try (
+ let inferred_v = infer_exp env v in
+ begin match typ_of inferred_v, n with
+ | Typ_aux (Typ_id id, _), E_aux (E_id field, (f_l, _)) ->
+ let (hi, lo) = Env.get_bitfield_range f_l id field env in
+ let hi, lo = mk_exp ~loc:l (E_lit (L_aux (L_num hi, l))), mk_exp ~loc:l (E_lit (L_aux (L_num lo, l))) in
+ infer_exp env (E_aux (E_vector_subrange (E_aux (E_field (v, Id_aux (Id "bits", f_l)), (l, ())), hi, lo), (l, ())))
+ | _, _ ->
+ typ_error env l "Vector access could not be interpreted as a bitfield access"
+ end
+ ) with
+ | Type_error (_, err_l', err') ->
+ typ_raise err_env err_l (Err_because (err, err_l', err')))
+ | exn -> raise exn
+ end
| E_vector_update (v, n, exp) -> infer_exp env (E_aux (E_app (mk_id "vector_update", [v; n; exp]), (l, ())))
| E_vector_update_subrange (v, n, m, exp) -> infer_exp env (E_aux (E_app (mk_id "vector_update_subrange", [v; n; m; exp]), (l, ())))
| E_vector_append (v1, E_aux (E_vector [], _)) -> infer_exp env v1
@@ -5138,22 +5184,55 @@ let rec check_typedef : 'a. Env.t -> 'a type_def -> (tannot def) list * Env.t =
[DEF_type (TD_aux (tdef, (l, None)))], env
| TD_enum (id, ids, _) ->
[DEF_type (TD_aux (tdef, (l, None)))], Env.add_enum id ids env
+ | TD_bitfield (id, typ, ranges) when !opt_new_bitfields ->
+ let typ = Env.expand_synonyms env typ in
+ begin match typ with
+ (* The type of a bitfield must be a constant-width bitvector *)
+ | Typ_aux (Typ_app (v, [A_aux (A_nexp (Nexp_aux (Nexp_constant size, _)), _);
+ A_aux (A_order order, _)]), _)
+ when string_of_id v = "bitvector" ->
+ let size = Big_int.to_int size in
+ let eval_index_nexp l nexp =
+ match int_of_nexp_opt (nexp_simp (Env.expand_nexp_synonyms env nexp)) with
+ | Some i -> i
+ | None -> typ_error env l ("This numeric expression must evaluate to a constant: " ^ string_of_nexp nexp)
+ in
+ let record_tdef = TD_record (id, mk_typquant [], [(typ, mk_id "bits")], false) in
+ let ranges =
+ List.fold_left (fun ranges (field, range) ->
+ match range with
+ | BF_aux (BF_single nexp, l) ->
+ let n = eval_index_nexp l nexp in
+ Bindings.add field (n, n) ranges
+ | BF_aux (BF_range (hi, lo), l) ->
+ let hi, lo = eval_index_nexp l hi, eval_index_nexp l lo in
+ Bindings.add field (hi, lo) ranges
+ | BF_aux (BF_concat _, _) ->
+ typ_error env l "Bitfield concatenation ranges are not supported"
+ ) Bindings.empty ranges
+ in
+ [DEF_type (TD_aux (record_tdef, (l, None)))],
+ env
+ |> Env.add_record id (mk_typquant []) [(typ, mk_id "bits")]
+ |> Env.add_bitfield id ranges
+ | _ ->
+ typ_error env l "Underlying bitfield type must be a constant-width bitvector"
+ end
| TD_bitfield (id, typ, ranges) ->
let typ = Env.expand_synonyms env typ in
- begin
- match typ with
- (* The type of a bitfield must be a constant-width bitvector *)
- | Typ_aux (Typ_app (v, [A_aux (A_nexp (Nexp_aux (Nexp_constant size, _)), _);
- A_aux (A_order order, _)]), _)
- when string_of_id v = "bitvector" ->
- let size = Big_int.to_int size in
- let eval_index_nexp env nexp =
- int_of_nexp_opt (nexp_simp (Env.expand_nexp_synonyms env nexp)) in
- let (Defs defs), env =
- check env (Bitfield.macro (eval_index_nexp env, (typ_error env)) id size order ranges) in
- defs, env
- | _ ->
- typ_error env l "Bad bitfield type"
+ begin match typ with
+ (* The type of a bitfield must be a constant-width bitvector *)
+ | Typ_aux (Typ_app (v, [A_aux (A_nexp (Nexp_aux (Nexp_constant size, _)), _);
+ A_aux (A_order order, _)]), _)
+ when string_of_id v = "bitvector" ->
+ let size = Big_int.to_int size in
+ let eval_index_nexp env nexp =
+ int_of_nexp_opt (nexp_simp (Env.expand_nexp_synonyms env nexp)) in
+ let (Defs defs), env =
+ check env (Bitfield.macro (eval_index_nexp env, (typ_error env)) id size order ranges) in
+ defs, env
+ | _ ->
+ typ_error env l "Underlying bitfield type must be a constant-width bitvector"
end
and check_scattered : 'a. Env.t -> 'a scattered_def -> (tannot def) list * Env.t =
diff --git a/src/type_check.mli b/src/type_check.mli
index 711f2411..76b38557 100644
--- a/src/type_check.mli
+++ b/src/type_check.mli
@@ -80,6 +80,9 @@ val opt_smt_linearize : bool ref
(** Allow use of div and mod when rewriting nexps *)
val opt_smt_div : bool ref
+(** Use new bitfield syntax, more compatible with ASL *)
+val opt_new_bitfields : bool ref
+
(** {2 Type errors} *)
type type_error =