Skip to content

Commit cea1fbb

Browse files
authored
Assorted bug fixes (#1637)
* Fix an outdated comment * Fix an issue where --c-no-mangle could cause name clashes Fix issues with recent Verilator versions. - The --sv-padding option is removed. It is now always on, as this behaviour is technically required by the SystemVerilog spec and Verilator now enforces this. - Verilator is now stricter about hextoa, bintoa, and itoa. Use $sformatf directly. Add a regression test for 1555
1 parent 2e284b5 commit cea1fbb

8 files changed

Lines changed: 99 additions & 111 deletions

File tree

src/lib/constant_fold.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ let rec run frame =
157157
| Interpreter.Effect_request _ -> assert false (* effectful, raise exception to abort constant folding *)
158158

159159
(** This rewriting pass looks for function applications (E_app) expressions where every argument is a literal. It passes
160-
these expressions to the OCaml interpreter in interpreter.ml, and reconstructs the values returned back into
160+
these expressions to the Rocq-derived interpreter in interpreter.ml, and reconstructs the values returned back into
161161
expressions which are then re-typechecked and re-inserted back into the AST.
162162
163163
We don't use the effect system to decide if expressions are safe to evaluate, because this ignores I/O, and would

src/sail_c_backend/c_backend.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,8 @@ module Codegen (Config : CODEGEN_CONFIG) = struct
989989
let has_prefix prefix s =
990990
if String.length s < String.length prefix then false else String.sub s 0 (String.length prefix) = prefix
991991

992-
let has_sail_prefix s = has_prefix "sail_" s || has_prefix "Sail_" s || has_prefix "SAIL_" s
992+
let has_bad_prefix s =
993+
has_prefix "sail_" s || has_prefix "Sail_" s || has_prefix "SAIL_" s || has_prefix "undefined_" s
993994

994995
(* Prefix to function name in definitions. *)
995996
let class_impl_prefix () = if Config.cpp then Config.cpp_class_name ^ "::" else ""
@@ -1013,7 +1014,7 @@ module Codegen (Config : CODEGEN_CONFIG) = struct
10131014
&& (not (Util.StringSet.mem s Keywords.c_reserved_words))
10141015
&& (not (Util.StringSet.mem s Keywords.c_used_words))
10151016
&& (not (Util.StringSet.mem s Config.reserved_words))
1016-
&& (not (has_sail_prefix s))
1017+
&& (not (has_bad_prefix s))
10171018
&& not (c_int_type_name s)
10181019
in
10191020
(not Config.no_mangle) || valid_name s

src/sail_sv_backend/generate_primop2.ml

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -157,43 +157,27 @@ module Make
157157
(* If the width is a multiple of four, format as hexadecimal.
158158
We take care to ensure the formatting is identical to other
159159
Sail backends. *)
160-
let zeros = Jib_util.name (mk_id "zeros") in
161160
let bstr = Jib_util.name (mk_id "bstr") in
162161
if width mod 4 = 0 then (
163162
let zeros_init = String.make (width / 4) '0' in
164163
[
165-
SVS_var (zeros, CT_string, None);
166164
SVS_var (bstr, CT_string, None);
167-
svs_raw "bstr.hextoa(b)" ~inputs:[b] ~outputs:[bstr];
168-
svs_raw (sprintf "zeros = \"%s\"" zeros_init) ~outputs:[zeros];
169-
svs_raw
170-
(sprintf
171-
"out_str = {in_str, s, $sformatf(\"0x%%s\", zeros.substr(0, %d - bstr.len()), bstr.toupper()), \
172-
\"\\n\"}"
173-
((width / 4) - 1)
174-
)
175-
~inputs:[in_str; s; zeros; bstr] ~outputs:[out_str];
165+
svs_raw "bstr = $sformatf(\"%h\", b)" ~inputs:[b] ~outputs:[bstr];
166+
svs_raw "out_str = {in_str, s, \"0x\", bstr.toupper(), \"\\n\"}" ~inputs:[in_str; s; bstr]
167+
~outputs:[out_str];
176168
SVS_assign (SVP_id Jib_util.return, Unit);
177169
]
178170
|> List.map mk_statement
179171
)
180-
else (
181-
let zeros_init = String.make width '0' in
172+
else
182173
[
183-
SVS_var (zeros, CT_string, None);
184174
SVS_var (bstr, CT_string, None);
185-
svs_raw "bstr.bintoa(b)" ~inputs:[b] ~outputs:[bstr];
186-
svs_raw (sprintf "zeros = \"%s\"" zeros_init) ~outputs:[zeros];
187-
svs_raw
188-
(sprintf
189-
"out_str = {in_str, s, $sformatf(\"0b%%s\", zeros.substr(0, %d - bstr.len())), bstr, \"\\n\"}"
190-
(width - 1)
191-
)
192-
~inputs:[in_str; s; bstr; zeros] ~outputs:[out_str];
175+
svs_raw "bstr = $sformatf(\"%b\", b)" ~inputs:[b] ~outputs:[bstr];
176+
svs_raw "out_str = {in_str, s, \"0b\", bstr.toupper(), \"\\n\"}" ~inputs:[in_str; s; bstr]
177+
~outputs:[out_str];
193178
SVS_assign (SVP_id Jib_util.return, Unit);
194179
]
195180
|> List.map mk_statement
196-
)
197181
)
198182
in
199183
SVD_module
@@ -231,8 +215,8 @@ module Make
231215
(List.map mk_statement
232216
[
233217
svs_raw (sprintf "zeros = \"%s\"" (String.make width '0')) ~outputs:[zeros];
234-
svs_raw (sprintf "hexstr.hextoa(b.sb_bits)") ~inputs:[b] ~outputs:[hexstr];
235-
svs_raw (sprintf "binstr.bintoa(b.sb_bits)") ~inputs:[b] ~outputs:[binstr];
218+
svs_raw (sprintf "hexstr.hextoa(int'(b.sb_bits))") ~inputs:[b] ~outputs:[hexstr];
219+
svs_raw (sprintf "binstr.bintoa(int'(b.sb_bits))") ~inputs:[b] ~outputs:[binstr];
236220
svs_raw
237221
(sprintf "%s = {in_str, s}" (string_of_name ~zencode:false (tempstr 0)))
238222
~inputs:[in_str; s]
@@ -306,15 +290,15 @@ module Make
306290
if Config.no_strings then [svs_raw "return SAIL_UNIT"]
307291
else if width mod 4 = 0 then
308292
[
309-
svs_raw "bstr.hextoa(b)" ~inputs:[b] ~outputs:[bstr];
293+
svs_raw "bstr.hextoa(int'(b))" ~inputs:[b] ~outputs:[bstr];
310294
svs_raw (pf "zeros = \"%s\"" (String.make (width / 4) '0')) ~outputs:[zeros];
311295
svs_raw
312296
(pf "return {\"0x\", zeros.substr(0, %d - bstr.len()), bstr.toupper()}" ((width / 4) - 1))
313297
~inputs:[zeros; bstr];
314298
]
315299
else
316300
[
317-
svs_raw "bstr.bintoa(b)" ~inputs:[b] ~outputs:[bstr];
301+
svs_raw "bstr.bintoa(int'(b))" ~inputs:[b] ~outputs:[bstr];
318302
svs_raw (pf "zeros = \"%s\"" (String.make width '0')) ~outputs:[zeros];
319303
svs_raw (pf "return {\"0b\", zeros.substr(0, %d - bstr.len()), bstr}" (width - 1)) ~inputs:[zeros; bstr];
320304
]
@@ -374,7 +358,7 @@ module Make
374358
SVS_var (n, CT_bool, None);
375359
SVS_var (p, CT_string, None);
376360
svs_raw "is_negative = signed'(i) < 0" ~inputs:[i] ~outputs:[n];
377-
svs_raw "s.hextoa(is_negative ? (-i) : i)" ~inputs:[i; n] ~outputs:[s];
361+
svs_raw "s = $sformatf(\"%0h\", is_negative ? (-i) : i)" ~inputs:[i; n] ~outputs:[s];
378362
svs_raw "prefix = is_negative ? \"-0x\" : \"0x\"" ~inputs:[n] ~outputs:[p];
379363
SVS_return (Fn ("str.++", [Var p; Var s]));
380364
]
@@ -407,7 +391,7 @@ module Make
407391
SVS_var (n, CT_bool, None);
408392
SVS_var (p, CT_string, None);
409393
svs_raw "is_negative = signed'(i) < 0" ~inputs:[i] ~outputs:[n];
410-
svs_raw "s.hextoa(is_negative ? (-i) : i)" ~inputs:[i; n] ~outputs:[s];
394+
svs_raw "s = $sformatf(\"%0h\", is_negative ? (-i) : i)" ~inputs:[i; n] ~outputs:[s];
411395
svs_raw "s = s.toupper()" ~inputs:[s] ~outputs:[s];
412396
svs_raw "prefix = is_negative ? \"-0x\" : \"0x\"" ~inputs:[n] ~outputs:[p];
413397
SVS_return (Fn ("str.++", [Var p; Var s]));
@@ -436,7 +420,7 @@ module Make
436420
(List.map mk_statement
437421
[
438422
SVS_var (s, CT_string, None);
439-
svs_raw "s.itoa(i)" ~inputs:[i] ~outputs:[s];
423+
svs_raw "s = $sformatf(\"%0d\", i)" ~inputs:[i] ~outputs:[s];
440424
SVS_return (Var s);
441425
]
442426
)

src/sail_sv_backend/jib_sv.ml

Lines changed: 52 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ module type CONFIG = sig
103103
val no_packed : bool
104104
val no_assertions : bool
105105
val never_pack_unions : bool
106-
val union_padding : bool
107106
val no_unions : bool
108107
val unreachable : string list
109108
val no_write_flush : bool
@@ -184,14 +183,19 @@ module Make (Config : CONFIG) = struct
184183
let rec bit_width ctx = function
185184
| CT_unit | CT_bool -> Some 1
186185
| CT_fbits len -> Some len
187-
| CT_lbits -> Some Config.max_unknown_bitvector_width
186+
| CT_lbits ->
187+
let w = Config.max_unknown_bitvector_width in
188+
Some (required_width (Big_int.of_int (w - 1)) + 1 + w)
188189
| CT_enum enum_id ->
189190
let members = Jib_compile.enum_members Parse_ast.Unknown ctx enum_id in
190191
Some (required_width (Big_int.of_int (IdSet.cardinal members - 1)))
191192
| CT_constant c -> Some (required_width c)
192193
| CT_variant _ as ctyp ->
194+
let open Util.Option_monad in
193195
let ctors = Jib_compile.variant_constructor_bindings Parse_ast.Unknown ctx ctyp |> snd |> Bindings.bindings in
194-
List.map (fun (_, ctyp) -> bit_width ctx ctyp) ctors |> Util.option_all |> Option.map (List.fold_left max 1)
196+
let* ctor_widths = List.map (fun (_, ctyp) -> bit_width ctx ctyp) ctors |> Util.option_all in
197+
let max_width = List.fold_left max 1 ctor_widths in
198+
Some (max_width + required_width (Big_int.of_int (List.length ctors - 1)))
195199
| CT_struct _ as ctyp ->
196200
let fields = Jib_compile.struct_field_bindings Parse_ast.Unknown ctx ctyp |> snd |> Bindings.bindings in
197201
List.map (fun (_, ctyp) -> bit_width ctx ctyp) fields |> Util.option_all |> Option.map (List.fold_left ( + ) 0)
@@ -319,7 +323,9 @@ module Make (Config : CONFIG) = struct
319323
Reporting.unreachable (id_loc id) __POS__ "Abstract types not supported for SystemVerilog target"
320324
| CTD_abbrev _ -> empty
321325
| CTD_enum (id, ids) ->
322-
string "typedef" ^^ space ^^ string "enum" ^^ space
326+
let width = required_width (Big_int.of_int (List.length ids - 1)) in
327+
let width_doc = lbracket ^^ string (string_of_int (width - 1)) ^^ colon ^^ char '0' ^^ rbracket in
328+
string "typedef" ^^ space ^^ string "enum" ^^ space ^^ width_doc ^^ space
323329
^^ group (lbrace ^^ nest 4 (hardline ^^ separate_map (comma ^^ hardline) pp_id ids) ^^ hardline ^^ rbrace)
324330
^^ space ^^ sv_type_id id ^^ semi
325331
| CTD_struct (id, _, fields) ->
@@ -339,11 +345,13 @@ module Make (Config : CONFIG) = struct
339345
let sv_ctor (id, ctyp) = wrap_type ctyp (pp_id id) in
340346
let tag_type = string ("sailtag_" ^ pp_id_string id) in
341347
let value_type = string ("sailunion_" ^ pp_id_string id) in
348+
let tag_width = required_width (Big_int.of_int (List.length ctors - 1)) in
342349
let kind_enum =
343350
separate space
344351
[
345352
string "typedef";
346353
string "enum";
354+
lbracket ^^ string (string_of_int (tag_width - 1)) ^^ colon ^^ char '0' ^^ rbracket;
347355
group (lbrace ^^ nest 4 (hardline ^^ separate_map (comma ^^ hardline) kind_id ctors) ^^ hardline ^^ rbrace);
348356
tag_type ^^ semi;
349357
]
@@ -393,84 +401,54 @@ module Make (Config : CONFIG) = struct
393401
ctors
394402
in
395403
let constructors =
396-
if Config.union_padding then
397-
List.map
398-
(fun (_, (ctor_id, ctyp, padding_type, required_padding)) ->
399-
separate space [string "function"; string "automatic"; sv_type_id id; pp_id ctor_id]
400-
^^ parens (wrap_type ctyp (char 'v'))
401-
^^ semi
402-
^^ nest 4
403-
(hardline ^^ sv_type_id id ^^ space ^^ char 'r' ^^ semi ^^ hardline
404-
^^ string ("sailunion_" ^ pp_id_string id)
405-
^^ space ^^ char 'u' ^^ semi ^^ hardline ^^ padding_type ^^ space ^^ char 'p' ^^ semi ^^ hardline
406-
^^ separate space
407-
[
408-
string "r.tag";
409-
equals;
410-
string_of_id ctor_id |> Util.zencode_string |> String.uppercase_ascii |> string;
411-
]
412-
^^ semi ^^ hardline
413-
^^ separate space [char 'p' ^^ dot ^^ pp_id ctor_id; equals; char 'v']
414-
^^ semi ^^ hardline
415-
^^ ( if required_padding > 0 then
416-
separate space
417-
[
418-
char 'p' ^^ dot ^^ string "padding";
419-
equals;
420-
ksprintf string "%d'b%s" required_padding (String.make required_padding '0');
421-
]
422-
^^ semi ^^ hardline
423-
else empty
424-
)
425-
^^ separate space [char 'u' ^^ dot ^^ pp_id ctor_id; equals; char 'p']
426-
^^ semi ^^ hardline
427-
^^ separate space [string "r.value"; equals; char 'u']
428-
^^ semi ^^ hardline ^^ string "return" ^^ space ^^ char 'r' ^^ semi
429-
)
430-
^^ hardline ^^ string "endfunction"
431-
)
432-
padding_structs
433-
else
434-
List.map
435-
(fun (ctor_id, ctyp) ->
436-
separate space [string "function"; string "automatic"; sv_type_id id; pp_id ctor_id]
437-
^^ parens (wrap_type ctyp (char 'v'))
438-
^^ semi
439-
^^ nest 4
440-
(hardline ^^ sv_type_id id ^^ space ^^ char 'r' ^^ semi ^^ hardline
441-
^^ string ("sailunion_" ^ pp_id_string id)
442-
^^ space ^^ char 'u' ^^ semi ^^ hardline
443-
^^ separate space
444-
[
445-
string "r.tag";
446-
equals;
447-
string_of_id ctor_id |> Util.zencode_string |> String.uppercase_ascii |> string;
448-
]
449-
^^ semi ^^ hardline
450-
^^ separate space [char 'u' ^^ dot ^^ pp_id ctor_id; equals; char 'v']
451-
^^ semi ^^ hardline
452-
^^ separate space [string "r.value"; equals; char 'u']
453-
^^ semi ^^ hardline ^^ string "return" ^^ space ^^ char 'r' ^^ semi
454-
)
455-
^^ hardline ^^ string "endfunction"
456-
)
457-
ctors
404+
List.map
405+
(fun (_, (ctor_id, ctyp, padding_type, required_padding)) ->
406+
separate space [string "function"; string "automatic"; sv_type_id id; pp_id ctor_id]
407+
^^ parens (wrap_type ctyp (char 'v'))
408+
^^ semi
409+
^^ nest 4
410+
(hardline ^^ sv_type_id id ^^ space ^^ char 'r' ^^ semi ^^ hardline
411+
^^ string ("sailunion_" ^ pp_id_string id)
412+
^^ space ^^ char 'u' ^^ semi ^^ hardline ^^ padding_type ^^ space ^^ char 'p' ^^ semi ^^ hardline
413+
^^ separate space
414+
[
415+
string "r.tag";
416+
equals;
417+
string_of_id ctor_id |> Util.zencode_string |> String.uppercase_ascii |> string;
418+
]
419+
^^ semi ^^ hardline
420+
^^ separate space [char 'p' ^^ dot ^^ pp_id ctor_id; equals; char 'v']
421+
^^ semi ^^ hardline
422+
^^ ( if required_padding > 0 then
423+
separate space
424+
[
425+
char 'p' ^^ dot ^^ string "padding";
426+
equals;
427+
ksprintf string "%d'b%s" required_padding (String.make required_padding '0');
428+
]
429+
^^ semi ^^ hardline
430+
else empty
431+
)
432+
^^ separate space [char 'u' ^^ dot ^^ pp_id ctor_id; equals; char 'p']
433+
^^ semi ^^ hardline
434+
^^ separate space [string "r.value"; equals; char 'u']
435+
^^ semi ^^ hardline ^^ string "return" ^^ space ^^ char 'r' ^^ semi
436+
)
437+
^^ hardline ^^ string "endfunction"
438+
)
439+
padding_structs
458440
in
459441
let sv_padded_ctor (_, (ctor_id, _, padding_type, _)) = padding_type ^^ space ^^ pp_id ctor_id in
460-
(if Config.union_padding then separate_map (twice hardline) fst padding_structs ^^ twice hardline else empty)
442+
separate_map (twice hardline) fst padding_structs
443+
^^ twice hardline
461444
^^ separate space
462445
[
463446
string "typedef";
464447
(if Config.no_unions then string "struct" else string "union");
465448
string "packed";
466449
group
467450
(lbrace
468-
^^ nest 4
469-
(hardline
470-
^^
471-
if Config.union_padding then separate_map (semi ^^ hardline) sv_padded_ctor padding_structs
472-
else separate_map (semi ^^ hardline) sv_ctor ctors
473-
)
451+
^^ nest 4 (hardline ^^ separate_map (semi ^^ hardline) sv_padded_ctor padding_structs)
474452
^^ semi ^^ hardline ^^ rbrace
475453
);
476454
value_type ^^ semi;
@@ -666,7 +644,7 @@ module Make (Config : CONFIG) = struct
666644
[pp_smt v ^^ dot ^^ string "tag"; string "=="; string (ctor |> zencode_id |> String.uppercase_ascii)]
667645
)
668646
| Unwrap (ctor, packed, v) ->
669-
let packed_ctor = if Config.union_padding then pp_id ctor ^^ dot ^^ pp_id ctor else pp_id ctor in
647+
let packed_ctor = pp_id ctor ^^ dot ^^ pp_id ctor in
670648
if packed then pp_smt v ^^ dot ^^ string "value" ^^ dot ^^ packed_ctor else pp_smt v ^^ dot ^^ pp_id ctor
671649
| Field (_, field, v) -> pp_smt v ^^ dot ^^ pp_id field
672650
| Ite (cond, then_exp, else_exp) ->

src/sail_sv_backend/jib_sv.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ module type CONFIG = sig
7878
val no_assertions : bool
7979

8080
val never_pack_unions : bool
81-
val union_padding : bool
8281
val no_unions : bool
8382
val unreachable : string list
8483
val no_write_flush : bool

src/sail_sv_backend/sail_plugin_sv.ml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ let opt_no_strings = ref false
101101
let opt_no_packed = ref false
102102
let opt_no_assertions = ref false
103103
let opt_never_pack_unions = ref false
104-
let opt_padding = ref false
105104
let opt_no_unions = ref false
106105
let opt_nomem = ref false
107106
let opt_no_assert_fatal = ref false
@@ -198,7 +197,6 @@ let verilog_options =
198197
(Flag.create ~prefix:["sv"] "no_packed", Arg.Set opt_no_packed, "don't emit packed datastructures");
199198
(Flag.create ~prefix:["sv"] "no_assertions", Arg.Set opt_no_assertions, "ignore all Sail asserts");
200199
(Flag.create ~prefix:["sv"] "never_pack_unions", Arg.Set opt_never_pack_unions, "never emit a packed union");
201-
(Flag.create ~prefix:["sv"] "padding", Arg.Set opt_padding, "add padding on packed unions");
202200
( Flag.create ~prefix:["sv"] ~arg:"functionname" "unreachable",
203201
Arg.String (fun fn -> opt_unreachable := fn :: !opt_unreachable),
204202
"Mark function as unreachable."
@@ -486,7 +484,6 @@ let verilog_target out_opt { ast; effect_info; env; default_sail_dir; _ } =
486484
let no_packed = !opt_no_packed
487485
let no_assertions = !opt_no_assertions
488486
let never_pack_unions = !opt_never_pack_unions
489-
let union_padding = !opt_padding
490487
let no_unions = !opt_no_unions
491488
let unreachable = !opt_unreachable
492489
let comb = !opt_comb

test/c/issue1555.expect

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Is B

0 commit comments

Comments
 (0)