From e319b40ffcc72aa5e2a41d1c455455200d1898e5 Mon Sep 17 00:00:00 2001 From: Alasdair Date: Thu, 5 Dec 2024 15:35:44 +0000 Subject: [PATCH] SV: Improve toplevel generation --- lib/sv/sail_modules.sv | 35 ++++++++++++++++++++++- src/bin/dune | 2 +- src/sail_sv_backend/jib_sv.ml | 53 +++++++++++++++++++++++++++++++---- 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/lib/sv/sail_modules.sv b/lib/sv/sail_modules.sv index 74509bdae..3a3128621 100644 --- a/lib/sv/sail_modules.sv +++ b/lib/sv/sail_modules.sv @@ -102,6 +102,8 @@ endfunction import "DPI-C" function bit[7:0] sail_read_byte(logic [63:0] addr); import "DPI-C" function bit sail_read_tag(logic [63:0] addr); + +import "DPI-C" function void sail_write_byte(logic [63:0] addr, logic [7:0] b); `else logic [7:0] sail_memory [logic [63:0]]; @@ -115,6 +117,14 @@ typedef struct { typedef sail_write sail_memory_writes [$]; +function automatic void sail_flush_writes(sail_memory_writes writes); + foreach (writes[i]) begin +`ifdef SAIL_DPI_MEMORY + sail_write_byte(writes[i].paddr, writes[i].data); +`endif + end +endfunction + function automatic sail_bits emulator_read_mem(logic [63:0] addrsize, sail_bits addr, sail_int n); logic [63:0] paddr; logic [SAIL_BITS_WIDTH-1:0] buffer; @@ -163,6 +173,25 @@ module emulator_write_mem output sail_unit ret, output sail_memory_writes out_writes ); + always_comb begin + logic [63:0] paddr; + logic [SAIL_BITS_WIDTH-1:0] buffer; + logic [SAIL_INDEX_WIDTH-2:0] i; + sail_memory_writes tmp; + + buffer = value.bits; + paddr = addr.bits[63:0]; + tmp = in_writes; + + for (i = n[SAIL_INDEX_WIDTH-2:0]; i > 0; i = i - 1) begin + sail_write b; + b.paddr = paddr + (64'(i) - 1); + b.data = buffer[7 + ((i - 1) * 8) -: 8]; + tmp.push_back(b); + end + + out_writes = tmp; + end endmodule module emulator_write_mem_exclusive @@ -187,7 +216,11 @@ module emulator_write_tag endmodule function automatic string sail_string_of_bits(sail_bits bv); - return ""; + string hexstr; + string trimmed; + hexstr = $sformatf("%x", bv.bits); + trimmed = hexstr.substr(SAIL_BITS_WIDTH / 4 - (bv.size / 4), SAIL_BITS_WIDTH / 4 - 1).toupper(); + return {"0x", trimmed}; endfunction `endif diff --git a/src/bin/dune b/src/bin/dune index 396ddad7c..59d9f36af 100644 --- a/src/bin/dune +++ b/src/bin/dune @@ -177,7 +177,7 @@ (%{workspace_root}/lib/reverse_endianness.sail as lib/reverse_endianness.sail) - (%{workspace_root}/lib/rts.c as lib/rts.c) + (%{workspace_root}/lib/sv/sail_modules.sv as lib/sv/sail_modules.sv) (%{workspace_root}/lib/rts.h as lib/rts.h) (%{workspace_root}/lib/sail.c as lib/sail.c) (%{workspace_root}/lib/sail.h as lib/sail.h) diff --git a/src/sail_sv_backend/jib_sv.ml b/src/sail_sv_backend/jib_sv.ml index c5b70f5a5..c7fab8e5b 100644 --- a/src/sail_sv_backend/jib_sv.ml +++ b/src/sail_sv_backend/jib_sv.ml @@ -126,6 +126,16 @@ module AttributeParser (Info : ATTRIBUTE_INFO) = struct | Some (AD_aux (_, l)) -> raise (key_type_error ~expected:"boolean" key l) ) + let get_string ~default key obj_opt = + match obj_opt with + | None -> default + | Some obj -> ( + match List.assoc_opt key obj with + | None -> default + | Some (AD_aux (AD_string s, _)) -> s + | Some (AD_aux (_, l)) -> raise (key_type_error ~expected:"string" key l) + ) + let get_types ~arity obj_opt = let* types = Option.bind obj_opt (List.assoc_opt "types") in let ctyps = @@ -170,6 +180,20 @@ module AttributeParser (Info : ATTRIBUTE_INFO) = struct | None -> Some ctyp | Some _ -> raise (Reporting.err_general l "return_type field should not have positional argument") + let get_string_set ~default key obj_opt = + let add_to_set set = function + | AD_aux (AD_string s, _) -> StringSet.add s set + | AD_aux (_, l) -> raise (key_type_error ~expected:"string" key l) + in + match obj_opt with + | None -> default + | Some obj -> ( + match List.assoc_opt key obj with + | None -> default + | Some (AD_aux (AD_list xs, _)) -> List.fold_left add_to_set StringSet.empty xs + | Some (AD_aux (_, l)) -> raise (key_type_error ~expected:"boolean" key l) + ) + let get_dpi sets obj_opt = let* dpi = Option.bind obj_opt (List.assoc_opt "dpi") in match dpi with @@ -2130,6 +2154,11 @@ module Make (Config : CONFIG) = struct let clk = Attr.get_bool ~default:false "clk" attr in (* Type conversions for the module input signals derived from function arguments. *) let arg_conversions = Attr.get_types ~arity:(List.length arg_ctyps) attr in + (* Registers that are exposed as output ports *) + let exposed = Attr.get_string_set ~default:StringSet.empty "expose" attr in + (* Text used to bracket output *) + let prefix = Attr.get_string ~default:"SAIL START\\n" "prefix" attr in + let suffix = Attr.get_string ~default:"SAIL END\\n" "suffix" attr in let register_resets, register_inputs, register_outputs = Bindings.fold @@ -2141,6 +2170,11 @@ module Make (Config : CONFIG) = struct ) spec_info.registers ([], [], []) in + let exposed_registers = + Bindings.fold + (fun reg ctyp ports -> if StringSet.mem (string_of_id reg) exposed then (reg, ctyp) :: ports else ports) + spec_info.registers [] + in let memory_writes = [ SVD_var (Name (mk_id "empty_memory_writes", -1), CT_memory_writes); @@ -2211,16 +2245,23 @@ module Make (Config : CONFIG) = struct ( if footprint.need_stdout then [ mk_statement - (svs_raw "$write({\"SAIL START\\n\", out_stdout, \"SAIL END\\n\"})" + (svs_raw + (Printf.sprintf "$write({\"%s\", out_stdout, \"%s\"})" prefix suffix) ~inputs:[Name (mk_id "out_stdout", -1)] ); ] else [] ) - @ - if footprint.need_stderr then - [mk_statement (svs_raw "$write(out_stderr)" ~inputs:[Name (mk_id "out_stderr", -1)])] - else [] + @ ( if footprint.need_stderr then + [mk_statement (svs_raw "$write(out_stderr)" ~inputs:[Name (mk_id "out_stderr", -1)])] + else [] + ) + @ List.map + (fun (reg, _) -> + mk_statement (SVS_continuous_assign (SVP_id (Name (reg, -1)), Var (Name (prepend_id "out_" reg, -1)))) + ) + exposed_registers + @ [mk_statement (svs_raw "sail_flush_writes(out_memory_writes)" ~inputs:[Name (mk_id "out_memory_writes", -1)])] in if clk then ( let reset_regs, inout_regs = @@ -2293,7 +2334,7 @@ module Make (Config : CONFIG) = struct [mk_port (name (mk_id "clk")) CT_bit; mk_port (name (mk_id "reset")) CT_bit] @ arg_ports @ register_resets else arg_ports ); - output_ports; + output_ports = output_ports @ List.map (fun (reg, ctyp) -> mk_port (Name (reg, -1)) ctyp) exposed_registers; defs = List.map mk_def defs; }