blob: 4970060c4d6fef12e37687c99cf36c4d76ad10c4 [file] [log] [blame]
(*
* Copyright 2018, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*)
/*- if configuration[me.instance.name].get('environment', 'c').lower() == 'cakeml' -*/
/*- from 'rpc-connector.c' import establish_recv_rpc, recv_first_rpc, complete_recv, begin_recv, begin_reply, complete_reply, reply_recv with context -*/
/*# Construct a dict from interface types to list of from ends indicies #*/
/*- set type_dict = {} -*/
/*- for f in me.parent.from_ends -*/
/*- set cur_list = type_dict.get(f.interface.type, []) -*/
/*- do cur_list.append(loop.index0) -*/
/*- do type_dict.update({f.interface.type: cur_list}) -*/
/*- endfor -*/
/*- set connector = namespace() -*/
/*- set int_types = ['uint8_t', 'uint16_t', 'uint32_t', 'uint64_t'] -*/
/*- macro cakeml_unmarshal(val, type, buf, offset) -*/
/*- if type in int_types -*/
/*- set sz = macros.sizeof(options.architecture, type) -*/
val /*? val ?*/ = Utils.bytes_to_int /*? buf ?*/ /*? offset ?*/ /*? sz ?*/;
val /*? offset ?*/ = /*? offset ?*/ + /*? sz ?*/;
/*- elif type == 'string' -*/
(* FIXME: compute the max length statically *)
val (/*? val ?*/, str_len) = Utils.read_c_string /*? buf ?*/ /*? offset ?*/
(Word8Array.length /*? buf ?*/);
val /*? offset ?*/ = /*? offset ?*/ + str_len + 1;
/*- else -*/
/*? raise(TemplateError('CakeML does not support this type: %s' % type)) ?*/
/*- endif -*/
/*- endmacro -*/
/*- macro cakeml_unmarshal_param(val, param, buf, offset) -*/
/*- if param.array -*/
/*? raise(TemplateError('CakeML does not support arrays')) ?*/
/*- endif -*/
/*? cakeml_unmarshal(val, param.type, buf, offset) ?*/
/*- endmacro -*/
/*- macro cakeml_marshal(val, type, buf, offset) -*/
/*- if type in int_types -*/
/*- set sz = macros.sizeof(options.architecture, type) -*/
val _ = Word8Array.copy (Utils.int_to_bytes /*? val ?*/ /*? sz ?*/) 0 /*? sz ?*/ /*? buf ?*/ /*? offset ?*/;
val /*? offset ?*/ = /*? offset ?*/ + /*? sz ?*/;
/*- elif type == 'string' -*/
val byte_array_output = Utils.string_to_bytes /*? val ?*/;
val len = Word8Array.length byte_array_output;
(* FIXME: compute buffer length statically (should be bsize) *)
val space_remaining = Word8Array.length /*? buf ?*/ - offset - 1;
val copy_len = if len <= space_remaining then len else space_remaining;
val _ = Word8Array.copy byte_array_output 0 copy_len /*? buf ?*/ /*? offset ?*/;
(* Null byte at the end of the string *)
val _ = Word8Array.update /*? buf ?*/ (/*? offset ?*/ + copy_len) (Word8.fromInt 0);
val /*? offset ?*/ = /*? offset ?*/ + copy_len + 1;
/*- else -*/
/*? raise(TemplateError('CakeML only supports int types right now')) ?*/
/*- endif -*/
/*- endmacro -*/
/*- macro cakeml_marshal_param(val, param, buf, offset) -*/
/*- if param.array -*/
/*? raise(TemplateError('CakeML does not support arrays')) ?*/
/*- endif -*/
/*? cakeml_marshal(val, param.type, buf, offset) ?*/
/*- endmacro -*/
/*- macro log2(val) -*/
/*- if val <= 2 ** 8 -*/
1
/*- elif val <= 2 ** 16 -*/
2
/*- elif val <= 2 ** 32 -*/
4
/*- elif val <= 2 ** 64 -*/
8
/*- else -*/
/*? raise(TemplateError('Value too large')) ?*/
/*- endif -*/
/*- endmacro -*/
open preamble basis componentTheory;
val _ = new_theory "connector";
val _ = translation_extends "component";
/*- set buffer = configuration[me.parent.name].get('buffer') -*/
/*- if buffer is none -*/
/*? establish_recv_rpc(connector, me.interface.name, language='cakeml') ?*/
/*- else -*/
/*? raise(TemplateError('CakeML connector does not support custom buffers')) ?*/
/*- endif -*/
val _ = ml_prog_update (open_module "Connector");
val rpc_loop_def = process_topdecs `
fun rpc_loop length badge =
/*- for from_type in type_dict.keys() -*/
/*- if not loop.first -*/
else
/*- endif -*/
if (
/*- for from_index in type_dict.get(from_type) -*/
/*- if not loop.first -*/
orelse
/*- endif -*/
badge = /*? connector.badges[from_index] ?*/
/*- endfor -*/
) then let
/*- set methods_len = len(from_type.methods) -*/
val offset = /*? connector.cakeml_reserved_buf ?*/;
(* Extract the method id if there is more than 1 method *)
/*- if methods_len <= 1 -*/
val method_id = 0;
/*- else -*/
val method_id_len = /*? log2(methods_len) ?*/;
val method_id = Utils.bytes_to_int /*? connector.recv_buffer ?*/ offset method_id_len;
val offset = offset + method_id_len;
/*- endif -*/
val _ = case method_id of
/*- for i, m in enumerate(from_type.methods) -*/
/*- set input_parameters = list(filter(lambda('x: x.direction in [\'refin\', \'in\', \'inout\']'), m.parameters)) -*/
/*- set output_parameters = list(filter(lambda('x: x.direction in [\'out\', \'inout\']'), m.parameters)) -*/
/*- if not loop.first -*/
|
/*- endif -*/
/*? i ?*/ (* /*? m.name ?*/ *) => let
(* Unmarshal input parameters *)
/*- for j, p in enumerate(input_parameters) -*/
/*? cakeml_unmarshal_param('input_val%s' % j, p, connector.recv_buffer, 'offset') ?*/
/*- endfor -*/
(* Call the implementation and deconstruct any result *)
val
(
/*- if m.return_type is not none -*/
return_val
/*- if len(output_parameters) > 0 -*/
,
/*- endif -*/
/*- endif -*/
/*- for j, _ in enumerate(output_parameters) -*/
/*- if not loop.first -*/
,
/*- endif -*/
result_val/*? j?*/
/*- endfor -*/
) = Component./*? me.interface.name ?*/_/*? m.name ?*/
/*- for j, _ in enumerate(input_parameters) -*/
input_val/*? j ?*/
/*- endfor -*/
/*- if len(input_parameters) == 0 -*/
()
/*- endif -*/
;
/*? complete_recv(connector) ?*/
/*? begin_reply(connector) ?*/
val offset = /*? connector.cakeml_reserved_buf ?*/;
(* Marshal return value *)
/*- if m.return_type is not none -*/
/*? cakeml_marshal('return_val', m.return_type, connector.send_buffer, 'offset') ?*/
/*- endif -*/
(* Marshal other output parameters *)
/*- for j, p in enumerate(output_parameters) -*/
/*? cakeml_marshal_param('result_val%s' % j, p, connector.send_buffer, 'offset') ?*/
/*- endfor -*/
val length = offset - /*? connector.cakeml_reserved_buf ?*/;
/*? reply_recv(connector, 'length', 'size', me.might_block()) ?*/
in rpc_loop size /*? connector.badge_symbol ?*/ end
/*- endfor -*/
| unused => (Utils.fail "Unexpected method_id")
in () end
/*- endfor -*/
else
(Utils.fail "Unexpected badge")
`;
val run_def = process_topdecs `
fun run u = let
/*? recv_first_rpc(connector, 'size', me.might_block()) ?*/
in (rpc_loop size /*? connector.badge_symbol ?*/) end;
`;
val _ = app append_prog [
rpc_loop_def,
run_def
];
val _ = ml_prog_update (close_module NONE);
val _ = export_theory ();
/*- endif -*/