Skip to content

Commit f3da818

Browse files
authored
Adding a wrapper to the lean backend to be able to handle more functions (#801)
This adds a wrapper to the lean backend, which allows handling additional bitvector operations. The implemented operations are: length, signExtend, zeroExtend, truncate and truncateLSB. The wrapper functions are in the namespace Sail.BitVec to avoid collisions. The remaining unimplemented operations require translating type conditions into Lean, which is not handled for now.
1 parent 161caca commit f3da818

13 files changed

+118
-11
lines changed

lib/vector.sail

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,11 @@ function neq_bits(x, y) = not_bool(eq_bits(x, y))
7777

7878
overload operator != = {neq_bits}
7979

80-
val bitvector_length = pure {coq: "length_mword", _: "length"} : forall 'n. bits('n) -> int('n)
80+
val bitvector_length = pure {
81+
coq: "length_mword",
82+
lean: "Sail.BitVec.length",
83+
_: "length"
84+
} : forall 'n. bits('n) -> int('n)
8185

8286
val vector_length = pure {
8387
ocaml: "length",
@@ -100,9 +104,15 @@ val print_bits = pure "print_bits" : forall 'n. (string, bits('n)) -> unit
100104
$[sv_module { stderr = true }]
101105
val prerr_bits = pure "prerr_bits" : forall 'n. (string, bits('n)) -> unit
102106

103-
val sail_sign_extend = pure "sign_extend" : forall 'n 'm, 'm >= 'n. (bits('n), int('m)) -> bits('m)
107+
val sail_sign_extend = pure {
108+
lean: "Sail.BitVec.signExtend",
109+
_: "sign_extend"
110+
} : forall 'n 'm, 'm >= 'n. (bits('n), int('m)) -> bits('m)
104111

105-
val sail_zero_extend = pure "zero_extend" : forall 'n 'm, 'm >= 'n. (bits('n), int('m)) -> bits('m)
112+
val sail_zero_extend = pure {
113+
lean: "Sail.BitVec.zeroExtend",
114+
_: "zero_extend"
115+
} : forall 'n 'm, 'm >= 'n. (bits('n), int('m)) -> bits('m)
106116

107117
/*!
108118
THIS`(v, n)` truncates `v`, keeping only the _least_ significant `n` bits.
@@ -112,6 +122,7 @@ val truncate = pure {
112122
interpreter: "vector_truncate",
113123
lem: "vector_truncate",
114124
coq: "vector_truncate",
125+
lean: "Sail.BitVec.truncate",
115126
_: "sail_truncate"
116127
} : forall 'm 'n, 'm >= 0 & 'm <= 'n. (bits('n), int('m)) -> bits('m)
117128

@@ -123,6 +134,7 @@ val truncateLSB = pure {
123134
interpreter: "vector_truncateLSB",
124135
lem: "vector_truncateLSB",
125136
coq: "vector_truncateLSB",
137+
lean: "Sail.BitVec.truncateLSB",
126138
_: "sail_truncateLSB"
127139
} : forall 'm 'n, 'm >= 0 & 'm <= 'n. (bits('n), int('m)) -> bits('m)
128140

src/bin/dune

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,4 +239,7 @@
239239
src/gen_lib/sail2_undefined_concurrency_interface.lem)
240240
(%{workspace_root}/src/gen_lib/sail2_values.lem
241241
as
242-
src/gen_lib/sail2_values.lem)))
242+
src/gen_lib/sail2_values.lem)
243+
(%{workspace_root}/src/sail_lean_backend/Sail/sail.lean
244+
as
245+
src/sail_lean_backend/Sail/sail.lean)))

src/sail_lean_backend/Sail/sail.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace Sail
2+
namespace BitVec
3+
4+
def length {w: Nat} (_: BitVec w): Nat := w
5+
6+
def signExtend {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' :=
7+
x.signExtend w'
8+
9+
def zeroExtend {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' :=
10+
x.zeroExtend w'
11+
12+
def truncate {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' :=
13+
x.truncate w'
14+
15+
def truncateLSB {w: Nat} (x: BitVec w) (w': Nat) : BitVec w' :=
16+
x.extractLsb' 0 w'
17+
18+
end BitVec
19+
end Sail

src/sail_lean_backend/pretty_print_lean.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ let rec doc_typ (Typ_aux (t, _) as typ) =
7676
| Typ_id (Id_aux (Id "int", _)) -> string "Int"
7777
| Typ_id (Id_aux (Id "bool", _)) -> string "Bool"
7878
| Typ_id (Id_aux (Id "bit", _)) -> parens (string "BitVec 1")
79+
| Typ_id (Id_aux (Id "nat", _)) -> string "Nat"
7980
| Typ_app (Id_aux (Id "bitvector", _), [A_aux (A_nexp m, _)]) -> string "BitVec " ^^ doc_nexp m
8081
| Typ_tuple ts -> parens (separate_map (space ^^ string "×" ^^ space) doc_typ ts)
8182
| Typ_id (Id_aux (Id id, _)) -> string id
@@ -199,5 +200,6 @@ let rec remove_imports (defs : (Libsail.Type_check.tannot, Libsail.Type_check.en
199200
let pp_ast_lean ({ defs; _ } as ast : Libsail.Type_check.typed_ast) o =
200201
let defs = remove_imports defs 0 in
201202
let output : document = separate_map empty doc_def defs in
203+
output_string o "import Sail.sail\n\n";
202204
print o output;
203205
()

src/sail_lean_backend/sail_plugin_lean.ml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ let lean_rewrites =
147147
("attach_effects", []);
148148
]
149149

150-
let create_lake_project (out_name : string) =
150+
let create_lake_project (out_name : string) default_sail_dir =
151151
(* Change the base directory if the option '--lean-output-dir' is set *)
152152
let base_dir = match !opt_lean_output_dir with Some dir -> dir | None -> "." in
153153
let project_dir = Filename.concat base_dir out_name in
@@ -164,22 +164,24 @@ let create_lake_project (out_name : string) =
164164
let out_name_camel = Libsail.Util.to_upper_camel_case out_name in
165165
let lakefile = open_out (Filename.concat project_dir "lakefile.toml") in
166166
output_string lakefile
167-
("name = \"" ^ out_name ^ "\"\ndefaultTargets = [\"" ^ out_name_camel ^ "\"]\n\n[[lean_lib]]\nname = \""
168-
^ out_name_camel ^ "\""
167+
("name = \"" ^ out_name ^ "\"\ndefaultTargets = [\"" ^ out_name_camel
168+
^ "\"]\n\n[[lean_lib]]\nname = \"Sail\"\n\n[[lean_lib]]\nname = \"" ^ out_name_camel ^ "\""
169169
);
170170
close_out lakefile;
171+
let sail_dir = Reporting.get_sail_dir default_sail_dir in
172+
let _ = Unix.system ("cp -r " ^ sail_dir ^ "/src/sail_lean_backend/Sail " ^ project_dir) in
171173
let project_main = open_out (Filename.concat project_dir (out_name_camel ^ ".lean")) in
172174
project_main
173175

174-
let output (out_name : string) ast =
175-
let project_main = create_lake_project out_name in
176+
let output (out_name : string) ast default_sail_dir =
177+
let project_main = create_lake_project out_name default_sail_dir in
176178
(* Uncomment for debug output of the Sail code after the rewrite passes *)
177179
(* Pretty_print_sail.output_ast stdout (Type_check.strip_ast ast); *)
178180
Pretty_print_lean.pp_ast_lean ast project_main;
179181
close_out project_main
180182

181-
let lean_target out_name { ctx; ast; effect_info; env; _ } =
183+
let lean_target out_name { default_sail_dir; ctx; ast; effect_info; env; _ } =
182184
let out_name = match out_name with Some f -> f | None -> "out" in
183-
output out_name ast
185+
output out_name ast default_sail_dir
184186

185187
let _ = Target.register ~name:"lean" ~options:lean_options ~rewrites:lean_rewrites ~asserts_termination:true lean_target

test/lean/bitvec_operation.expected.lean

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1+
import Sail.sail
2+
13
def bitvector_eq (x : BitVec 16) (y : BitVec 16) : Bool :=
24
(Eq x y)
35

46
def bitvector_neq (x : BitVec 16) (y : BitVec 16) : Bool :=
57
(Ne x y)
68

9+
def bitvector_len (x : BitVec 16) : Nat :=
10+
(Sail.BitVec.length x)
11+
12+
def bitvector_sign_extend (x : BitVec 16) : BitVec 32 :=
13+
(Sail.BitVec.signExtend x 32)
14+
15+
def bitvector_zero_extend (x : BitVec 16) : BitVec 32 :=
16+
(Sail.BitVec.zeroExtend x 32)
17+
18+
def bitvector_truncate (x : BitVec 32) : BitVec 16 :=
19+
(Sail.BitVec.truncate x 16)
20+
21+
def bitvector_truncateLSB (x : BitVec 32) : BitVec 16 :=
22+
(Sail.BitVec.truncateLSB x 16)
23+
724
def bitvector_append (x : BitVec 16) (y : BitVec 16) : BitVec 32 :=
825
(BitVec.append x y)
926

@@ -25,6 +42,12 @@ def bitvector_or (x : BitVec 16) (y : BitVec 16) : BitVec 16 :=
2542
def bitvector_xor (x : BitVec 16) (y : BitVec 16) : BitVec 16 :=
2643
(HXor.hXor x y)
2744

45+
def bitvector_unsigned (x : BitVec 16) : Nat :=
46+
(BitVec.toNat x)
47+
48+
def bitvector_signed (x : BitVec 16) : Int :=
49+
(BitVec.toInt x)
50+
2851
def initialize_registers : Unit :=
2952
()
3053

test/lean/bitvec_operation.sail

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@ function bitvector_neq(x, y) = {
1212
x != y
1313
}
1414

15+
val bitvector_len : bits(16) -> nat
16+
function bitvector_len(x) = {
17+
length (x)
18+
}
19+
20+
val bitvector_sign_extend : bits(16) -> bits(32)
21+
function bitvector_sign_extend(x) = {
22+
sail_sign_extend (x, 32)
23+
}
24+
25+
val bitvector_zero_extend : bits(16) -> bits(32)
26+
function bitvector_zero_extend(x) = {
27+
sail_zero_extend (x, 32)
28+
}
29+
30+
val bitvector_truncate : bits(32) -> bits(16)
31+
function bitvector_truncate(x) = {
32+
truncate (x, 16)
33+
}
34+
35+
val bitvector_truncateLSB : bits(32) -> bits(16)
36+
function bitvector_truncateLSB(x) = {
37+
truncateLSB (x, 16)
38+
}
39+
1540
val bitvector_append : (bits(16), bits(16)) -> bits(32)
1641
function bitvector_append(x, y) = {
1742
append (x, y)
@@ -47,3 +72,12 @@ function bitvector_xor(x, y) = {
4772
xor_vec (x, y)
4873
}
4974

75+
val bitvector_unsigned : bits(16) -> nat
76+
function bitvector_unsigned(x) = {
77+
unsigned (x)
78+
}
79+
80+
val bitvector_signed : bits(16) -> int
81+
function bitvector_signed(x) = {
82+
signed (x)
83+
}

test/lean/enum.expected.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Sail.sail
2+
13
inductive E where | A | B | C
24
deriving Inhabited
35

test/lean/extern.expected.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Sail.sail
2+
13
def extern_add : Int :=
24
(Int.add 5 4)
35

test/lean/extern_bitvec.expected.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Sail.sail
2+
13
def extern_const : BitVec 64 :=
24
(0xFFFF000012340000 : BitVec 64)
35

0 commit comments

Comments
 (0)