Skip to content

Commit

Permalink
added the start of operand details generation (for each instruction, …
Browse files Browse the repository at this point in the history
…what registers/literals/addresses it uses), added a do-not-modify warning at each generated file starts, improved smoke test
  • Loading branch information
moste00 committed Nov 7, 2024
1 parent c973000 commit 2e10078
Show file tree
Hide file tree
Showing 19 changed files with 10,157 additions and 7,077 deletions.
53 changes: 39 additions & 14 deletions .github/workflows/end2end-smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ jobs:
touch test_main.c
echo '#include "riscv_decode.gen.inc"' >> test_main.c
echo >> test_main.c
echo '#include "riscv_decode_compressed.gen.inc"' >> test_main.c
echo >> test_main.c
echo '#include "riscv_ast2str.gen.inc"' >> test_main.c
echo >> test_main.c
echo '#include "riscv_insn_mapping.gen.inc"' >> test_main.c
echo >> test_main.c
echo 'void main() {}' >> test_main.c
mv ../old_output/riscv_helpers_ast2str.h riscv_helpers_ast2str.h
Expand All @@ -68,19 +72,40 @@ jobs:
clang-format -i *
if diff -q riscv_ast.gen.inc ../old_output/riscv_ast.gen.inc > /dev/null 2>&1; then
if diff -q riscv_decode.gen.inc ../old_output/riscv_decode.gen.inc > /dev/null 2>&1; then
if diff -q riscv_ast2str.gen.inc ../old_output/riscv_ast2str.gen.inc > /dev/null 2>&1; then
echo "Success: The tool generates compiling C code that is identical to the files committed."
else
echo "Failure: The tool-generated ast stringification logic differ from the one committed in the repo"
exit 1
fi
else
echo "Failure: The tool-generated decoding logic differ from the one committed in the repo."
exit 1
fi
else
if ! diff -q riscv_ast.gen.inc ../old_output/riscv_ast.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated ast definition differ from the one committed in the repo."
exit 1
fi
fi
if ! diff -q riscv_decode.gen.inc ../old_output/riscv_decode.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated decoding logic differ from the one committed in the repo."
exit 1
fi
if ! diff -q riscv_decode_compressed.gen.inc ../old_output/riscv_decode_compressed.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated compressed (16-bit) decoding logic differ from the one committed in the repo."
exit 1
fi
if ! diff -q riscv_ast2str_tbls.gen.inc ../old_output/riscv_ast2str_tbls.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated stringification helpers differ from the one committed in the repo"
exit 1
fi
if ! diff -q riscv_ast2str.gen.inc ../old_output/riscv_ast2str.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated ast stringification logic differ from the one committed in the repo"
exit 1
fi
if ! diff -q riscv_insn_mapping.gen.inc ../old_output/riscv_insn_mapping.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated ast-id->instruction-id mapping logic differ from the one committed in the repo"
exit 1
fi
if ! diff -q riscv_insn.gen.inc ../old_output/riscv_insn.gen.gen.inc > /dev/null 2>&1; then
echo "Failure: The tool-generated instruction ids differ from the one committed in the repo"
exit 1
fi
echo "Success: The tool generates compiling C code that is identical to the files committed."
83 changes: 61 additions & 22 deletions bin/main.ml
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
open Libsail
open Type_check
open Ast

open Riscv_disasm_from_sail
open Constants
open Gen_decoder
open Gen_assembler
open Stringify

open Printexc

let get_generator_comment () =
let sail_hash = List.nth (Utils.read_file "sail.hash.txt") 0 in
let delimiter =
"======================================================================="
in
"/*"
^ String.concat "*/\n/*"
[
delimiter;

"This code was generated by the tool riscv_disasm_from_sail (see "
^ "https://github.com/moste00/riscv_disasm_from_sail)";

"from the sail model of RISC-V (see " ^
"https://github.com/riscv/sail-riscv) @ version " ^ sail_hash ^ ".";

"DO NOT MODIFY THIS CODE MANUALLY.";
" ";
"SPDX-License-Identifier: BSD-3-Clause";
delimiter;
]
^ "*/\n\n"

let mkdir_if_none_exists dirname =
try Sys.mkdir dirname 0o777 with Sys_error _ -> ()

Expand All @@ -13,11 +41,19 @@ let write_c_file ?(additional_includes = []) name code =

let oc = open_out ("riscv_disasm/" ^ name) in
let mk_include_lines incs =
String.concat "\n" (List.map (fun i -> "#include " ^ i ^ "\n") incs)
String.concat "\n"
(List.map
(fun i ->
let delimiter = if i.[0] = '<' || i.[0] = '"' then "" else "\"" in
"#include " ^ delimiter ^ i ^ delimiter ^ "\n"
)
incs
)
in
let include_string = mk_include_lines Constants.includes in
let include_string = mk_include_lines includes in
let additional_includes_string = mk_include_lines additional_includes in
let name_no_dots = String.map (fun c -> if c = '.' then '_' else c) name in
Printf.fprintf oc "%s" (get_generator_comment ());
Printf.fprintf oc "%s"
("#ifndef __" ^ String.capitalize_ascii name_no_dots ^ "__\n");
Printf.fprintf oc "%s"
Expand Down Expand Up @@ -68,11 +104,16 @@ let ctypedefs_str = Stringify.stringify_typdef ctypedefs

let analysis = Sail_analysis.analyze ast types

let dec = Gen_decoder.gen_decoder ast analysis
let dec = gen_decode_proc (gen_decoder ast_decode_mapping ast analysis)

let compressed_dec =
gen_decode_proc (gen_decoder ast_compressed_decode_mapping ast analysis)

let proc_dec = Gen_decoder.gen_decode_proc dec
let dec_str = stringify_decode_procedure dec typdefwalker

let proc_dec_str = Stringify.stringify_decode_procedure proc_dec typdefwalker
let compressed_dec_str =
stringify_decode_procedure ~c_proc_name:"decode_compressed" compressed_dec
typdefwalker

let asm = Gen_assembler.gen_asm ast analysis

Expand All @@ -86,28 +127,26 @@ let instr_types = Gen_instr_types.gen_instr_types analysis gen_instr_types_conf
let instr_types_str, instr_types_mapping_str =
Stringify.stringify_instr_types instr_types typdefwalker

let () = write_c_file Constants.ast_type_filename ctypedefs_str
let () =
write_c_file Constants.decode_logic_filename proc_dec_str
~additional_includes:["\"" ^ Constants.ast_type_filename ^ "\""]
let _ = Gen_operand_info.gen_operand_info ast analysis

let () = write_c_file ast_type_filename ctypedefs_str
let () =
write_c_file decode_logic_filename dec_str
~additional_includes:[ast_type_filename]
let () =
write_c_file Constants.assembler_filename asm_str
write_c_file compressed_decode_logic_filename compressed_dec_str
~additional_includes:[ast_type_filename]
let () =
write_c_file assembler_filename asm_str
~additional_includes:
[
"\"" ^ Constants.ast_type_filename ^ "\"";
"\"" ^ Constants.ast2str_tables_filename ^ "\"";
"\"riscv_helpers_ast2str.h\"";
]
[ast_type_filename; ast2str_tables_filename; "riscv_helpers_ast2str.h"]

let () =
write_c_file Constants.ast2str_tables_filename tables_str
~additional_includes:["\"" ^ Constants.ast_type_filename ^ "\""]
write_c_file ast2str_tables_filename tables_str
~additional_includes:[ast_type_filename]

let () =
write_c_file Constants.instr_types_filename instr_types_str
~additional_includes:["\"" ^ Constants.ast_type_filename ^ "\""]
let () = write_c_file instr_types_filename instr_types_str

let () =
write_c_file Constants.instr_types_mapping_filename instr_types_mapping_str
~additional_includes:["\"" ^ Constants.instr_types_filename ^ "\""]
write_c_file instr_types_mapping_filename instr_types_mapping_str
~additional_includes:[instr_types_filename]
4 changes: 4 additions & 0 deletions lib/constants.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ let ast_sail_destructuring_function = "execute"

let ast_decode_mapping = "encdec"

let ast_compressed_decode_mapping = "encdec_compressed"

let generated_ast_enum_suffix = "_node_type"

let generated_ast_payload_suffix = "_node"
Expand All @@ -18,6 +20,8 @@ let ast_type_filename = "riscv_ast.gen.inc"

let decode_logic_filename = "riscv_decode.gen.inc"

let compressed_decode_logic_filename = "riscv_decode_compressed.gen.inc"

let identifier_prefix = "RISCV_"

let ast_assembly_mapping = "assembly"
Expand Down
3 changes: 3 additions & 0 deletions lib/decode_procedure.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@ type stmt =
| Set_ast_next_case_member of value_xor_expr
| Ret_ast
| Block of stmt list
| Start_rule of string
| End_rule
(* delineate the beginning and end of an instruction group that implement one declarative rule*)

type decproc = Proc of stmt
22 changes: 12 additions & 10 deletions lib/gen_decoder.ml
Original file line number Diff line number Diff line change
Expand Up @@ -205,19 +205,19 @@ let calculate_instr_len state _ id _ typ =
state.instr_length <- Some (calculate_instr_length typ)
)

let gen_decode_rule state _ id tannot left right =
if id_to_str id = ast_decode_mapping then (
let gen_decode_rule decode_mappig_name state _ id tannot left right =
if id_to_str id = decode_mappig_name then (
let bindings, consequences = bind_args_and_create_consequences state left in
let conditions = create_conditions state right bindings in
state.decode_rules <- (conditions, consequences) :: state.decode_rules
)

let gen_decoder ast analysis =
let gen_decoder decode_mappig_name ast analysis =
let state = { analysis; decode_rules = []; instr_length = None } in
let decoder_gen_processor =
{
default_processor with
process_mapping_bidir_clause = gen_decode_rule;
process_mapping_bidir_clause = gen_decode_rule decode_mappig_name;
process_val = calculate_instr_len;
}
in
Expand Down Expand Up @@ -285,7 +285,7 @@ let gen_mapbind_stmt offsets (i, cond) body =
Block [switch; If (Is_struct_var_valid var_name, body)]
| _ -> body

let gen_stmt_from_conditions conds conseq_stmts =
let gen_stmt_from_conditions rule_name conds conseq_stmts =
let offsets = calculate_offsets conds in
let indices = List.mapi (fun i _ -> i) conds in
let conds_indexed = List.combine indices conds in
Expand All @@ -298,8 +298,10 @@ let gen_stmt_from_conditions conds conseq_stmts =
(Block (List.append bind_stmts conseq_stmts))
in
match assert_exprs with
| [] -> mapbind_stmt
| _ -> If (And assert_exprs, mapbind_stmt)
| [] -> Block [Start_rule rule_name; mapbind_stmt; End_rule]
| _ ->
Block
[Start_rule rule_name; If (And assert_exprs, mapbind_stmt); End_rule]

let gen_stmt_from_consequences consequences =
let head, bodies = consequences in
Expand All @@ -326,11 +328,11 @@ let gen_stmt_from_consequences consequences =
)
bodies
in
List.append (Set_ast_case case_name :: body_stmts) [Ret_ast]
(List.append (Set_ast_case case_name :: body_stmts) [Ret_ast], case_name)

let gen_stmt_from_rule rule =
let conditions, consequences = rule in
let conseq_stmts = gen_stmt_from_consequences consequences in
gen_stmt_from_conditions conditions conseq_stmts
let conseq_stmts, name = gen_stmt_from_consequences consequences in
gen_stmt_from_conditions name conditions conseq_stmts

let gen_decode_proc decoder = Proc (Block (List.map gen_stmt_from_rule decoder))
2 changes: 1 addition & 1 deletion lib/gen_decoder.mli
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ open Decoder
open Decode_procedure
open Sail_analysis

val gen_decoder : (tannot, env) ast -> sail_analysis_result -> decoder
val gen_decoder : string -> (tannot, env) ast -> sail_analysis_result -> decoder

val gen_decode_proc : decoder -> decproc
94 changes: 94 additions & 0 deletions lib/gen_operand_info.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
open Libsail
open Ast

open Sail_ast_foreach
open Sail_ast_processor
open Sail_utils
open Sail_analysis

open Utils

(* The four register files in RISCV and its standard extensions *)
(* The float and double register files overlap, but they should still
be counted as seperate for max clarity of information provided
by the generated disassembler *)
type regfile = Base | Float | Double | Vector
type operand = Reg of int * regfile

type operand_info = (string, operand list) Hashtbl.t

type operand_gen_iteration_state = {
analysis : sail_analysis_result;
info : operand_info;
}

let destructure_arglist args =
let (P_aux (args_pat, _)) = args in
match args_pat with
| P_app (id, arg_names) -> (
let args_tuple = Option.get (get_sole_element_or_none arg_names) in
match args_tuple with
| P_aux (P_tuple args, _) ->
print_endline
"\n--------------------SUCC----------------------------\n";
( id_to_str id,
List.map
(fun (P_aux (p, _)) ->
match p with P_id i -> id_to_str i | _ -> failwith "******"
)
args
)
| _ -> (id_to_str id, [])
)
| _ -> failwith "__++__"

let bind_regidx_args reg_indices_members arg_names =
let binding = Hashtbl.create (List.length reg_indices_members) in
List.iteri
(fun i arg_name ->
if List.mem i reg_indices_members then Hashtbl.add binding arg_name i
)
arg_names;
binding

let analyze_operands state _ fun_id func =
if id_to_str_noexn fun_id <> "execute" then
print_endline
("\n\n -------------------- ENCOUNTERED " ^ id_to_str_noexn fun_id
^ " FUNCTION, IGNORING IT \n\n"
)
else (
let (Pat_aux (pat, _)) = func in
let args, body =
match pat with Pat_exp (a, b) -> (a, b) | Pat_when (a, b, _) -> (a, b)
in
let case_name, arg_names = destructure_arglist args in
let reg_indices_members =
get_all_case_members_of_type_named state.analysis case_name "regidx"
in
let bound_args = bind_regidx_args reg_indices_members arg_names in
print_endline
("+++++++++++++++++++++++++++ IN CASE " ^ case_name
^ " +++++++++++++++++++++++++++++++"
);
Hashtbl.iter
(fun arg_name arg_idx ->
print_endline
("&&&&&&&&&&&&&&&&&&&&&& ARG " ^ arg_name ^ " IS ARG "
^ string_of_int arg_idx ^ " )))))) \n\n"
)
)
bound_args
)

let gen_operand_info ast analysis =
let processor =
{ default_processor with process_function_clause = analyze_operands }
in
let state = { analysis; info = Hashtbl.create 300 } in
foreach_node ast processor state;
print_endline
"\n\n\
================================== OPERAND ANALYSIS DONE \
=============================================== \n\n\
\ "
10 changes: 10 additions & 0 deletions lib/sail_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,13 @@ let get_all_cases_with_enum_members ana =
)
cases_type_sigs;
cases_with_enum_members

let get_all_case_members_of_type_named ana case_name type_name =
let cases_type_sigs = ana.type_ctx.union_cases_type_signatures in
let case_type_sig = Hashtbl.find cases_type_sigs case_name in
let case_type_sig_indexed = List.mapi (fun i t -> (i, t)) case_type_sig in
List.filter_map
(fun (i, t) ->
match t with Named_type name when name = type_name -> Some i | _ -> None
)
case_type_sig_indexed
Loading

0 comments on commit 2e10078

Please sign in to comment.