#include "amduat/format/pel.h" #include "amduat/format/json.h" #include "amduat/format/ref.h" #include "amduat/util/hex.h" #include #include #include const char *amduat_format_pel_status_name( amduat_pel_execution_status_t status) { switch (status) { case AMDUAT_PEL_EXEC_STATUS_OK: return "OK"; case AMDUAT_PEL_EXEC_STATUS_SCHEME_UNSUPPORTED: return "SCHEME_UNSUPPORTED"; case AMDUAT_PEL_EXEC_STATUS_INVALID_PROGRAM: return "INVALID_PROGRAM"; case AMDUAT_PEL_EXEC_STATUS_INVALID_INPUTS: return "INVALID_INPUTS"; case AMDUAT_PEL_EXEC_STATUS_RUNTIME_FAILED: return "RUNTIME_FAILED"; default: return "UNKNOWN"; } } const char *amduat_format_pel_error_kind_name( amduat_pel_execution_error_kind_t kind) { switch (kind) { case AMDUAT_PEL_EXEC_ERROR_NONE: return "NONE"; case AMDUAT_PEL_EXEC_ERROR_SCHEME: return "SCHEME"; case AMDUAT_PEL_EXEC_ERROR_PROGRAM: return "PROGRAM"; case AMDUAT_PEL_EXEC_ERROR_INPUTS: return "INPUTS"; case AMDUAT_PEL_EXEC_ERROR_RUNTIME: return "RUNTIME"; default: return "UNKNOWN"; } } const char *amduat_format_pel_node_status_name( amduat_pel_node_trace_status_t status) { switch (status) { case AMDUAT_PEL_NODE_TRACE_OK: return "NODE_OK"; case AMDUAT_PEL_NODE_TRACE_FAILED: return "NODE_FAILED"; case AMDUAT_PEL_NODE_TRACE_SKIPPED: return "NODE_SKIPPED"; default: return "NODE_UNKNOWN"; } } const char *amduat_format_pel_store_phase_name( amduat_pel_store_failure_phase_t phase) { switch (phase) { case AMDUAT_PEL_STORE_FAILURE_PROGRAM: return "PROGRAM"; case AMDUAT_PEL_STORE_FAILURE_INPUT: return "INPUT"; default: return "UNKNOWN"; } } const char *amduat_format_pel_store_error_name( amduat_pel_store_error_code_t code) { switch (code) { case AMDUAT_PEL_STORE_ERROR_NOT_FOUND: return "NOT_FOUND"; case AMDUAT_PEL_STORE_ERROR_INTEGRITY: return "INTEGRITY"; case AMDUAT_PEL_STORE_ERROR_UNSUPPORTED: return "UNSUPPORTED"; default: return "UNKNOWN"; } } const char *amduat_format_pel_kernel_kind_name( amduat_pel_kernel_op_kind_t kind) { switch (kind) { case AMDUAT_PEL_KERNEL_OP_CONCAT: return "concat"; case AMDUAT_PEL_KERNEL_OP_SLICE: return "slice"; case AMDUAT_PEL_KERNEL_OP_CONST: return "const"; case AMDUAT_PEL_KERNEL_OP_HASH_ASL1: return "hash_asl1"; default: return "unknown"; } } static char *amduat_format_hex_encode(amduat_octets_t bytes) { char *hex = NULL; if (!amduat_hex_encode_alloc(bytes.data, bytes.len, &hex)) { return NULL; } return hex; } static bool amduat_format_diagnostics_text( FILE *stream, const char *prefix, const amduat_pel_diagnostic_entry_t *diags, size_t diags_len) { size_t i; if (diags_len == 0) { return true; } if (prefix == NULL) { prefix = ""; } for (i = 0; i < diags_len; ++i) { char *msg_hex = amduat_format_hex_encode(diags[i].message); if (msg_hex == NULL) { return false; } fprintf(stream, "%sdiagnostic[%zu].code=%u\n", prefix, i, diags[i].code); fprintf(stream, "%sdiagnostic[%zu].message_hex=%s\n", prefix, i, msg_hex); free(msg_hex); } return true; } static bool amduat_format_diagnostics_json( FILE *stream, const amduat_pel_diagnostic_entry_t *diags, size_t diags_len) { size_t i; fputs("[", stream); for (i = 0; i < diags_len; ++i) { char *msg_hex = amduat_format_hex_encode(diags[i].message); if (msg_hex == NULL) { return false; } if (i != 0) { fputc(',', stream); } fprintf(stream, "{\"code\":%u,\"message_hex\":", diags[i].code); if (!amduat_format_json_escape( stream, amduat_octets(msg_hex, strlen(msg_hex)))) { free(msg_hex); return false; } fputs("}", stream); free(msg_hex); } fputs("]", stream); return true; } static bool amduat_format_program_text(FILE *stream, const amduat_pel_program_t *program) { size_t i; fprintf(stream, "nodes_len=%zu\n", program->nodes_len); fprintf(stream, "roots_len=%zu\n", program->roots_len); for (i = 0; i < program->nodes_len; ++i) { const amduat_pel_node_t *node = &program->nodes[i]; size_t j; char *params_hex; fprintf(stream, "node[%zu].id=%u\n", i, node->id); fprintf(stream, "node[%zu].op.name=%.*s\n", i, (int)node->op.name.len, node->op.name.data ? (const char *)node->op.name.data : ""); fprintf(stream, "node[%zu].op.version=%u\n", i, node->op.version); fprintf(stream, "node[%zu].inputs_len=%zu\n", i, node->inputs_len); for (j = 0; j < node->inputs_len; ++j) { const amduat_pel_dag_input_t *input = &node->inputs[j]; if (input->kind == AMDUAT_PEL_DAG_INPUT_EXTERNAL) { fprintf(stream, "node[%zu].input[%zu].kind=external\n", i, j); fprintf(stream, "node[%zu].input[%zu].external.input_index=%u\n", i, j, input->value.external.input_index); } else { fprintf(stream, "node[%zu].input[%zu].kind=node\n", i, j); fprintf(stream, "node[%zu].input[%zu].node.node_id=%u\n", i, j, input->value.node.node_id); fprintf(stream, "node[%zu].input[%zu].node.output_index=%u\n", i, j, input->value.node.output_index); } } params_hex = amduat_format_hex_encode(node->params); if (params_hex == NULL) { return false; } fprintf(stream, "node[%zu].params_len=%zu\n", i, node->params.len); fprintf(stream, "node[%zu].params_hex=%s\n", i, params_hex); free(params_hex); } for (i = 0; i < program->roots_len; ++i) { fprintf(stream, "root[%zu].node_id=%u\n", i, program->roots[i].node_id); fprintf(stream, "root[%zu].output_index=%u\n", i, program->roots[i].output_index); } return true; } static bool amduat_format_program_json(FILE *stream, const amduat_pel_program_t *program) { size_t i; fputs("{\"nodes\":[", stream); for (i = 0; i < program->nodes_len; ++i) { const amduat_pel_node_t *node = &program->nodes[i]; size_t j; char *params_hex; if (i != 0) { fputc(',', stream); } fputs("{\"id\":", stream); fprintf(stream, "%u", node->id); fputs(",\"op\":{\"name\":", stream); if (!amduat_format_json_escape(stream, node->op.name)) { return false; } fprintf(stream, ",\"version\":%u}", node->op.version); fputs(",\"inputs\":[", stream); for (j = 0; j < node->inputs_len; ++j) { const amduat_pel_dag_input_t *input = &node->inputs[j]; if (j != 0) { fputc(',', stream); } if (input->kind == AMDUAT_PEL_DAG_INPUT_EXTERNAL) { fprintf(stream, "{\"kind\":\"external\",\"input_index\":%u}", input->value.external.input_index); } else { fprintf(stream, "{\"kind\":\"node\",\"node_id\":%u,\"output_index\":%u}", input->value.node.node_id, input->value.node.output_index); } } fputs("]", stream); params_hex = amduat_format_hex_encode(node->params); if (params_hex == NULL) { return false; } fputs(",\"params_hex\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(params_hex, strlen(params_hex)))) { free(params_hex); return false; } free(params_hex); fputs("}", stream); } fputs("],\"roots\":[", stream); for (i = 0; i < program->roots_len; ++i) { if (i != 0) { fputc(',', stream); } fprintf(stream, "{\"node_id\":%u,\"output_index\":%u}", program->roots[i].node_id, program->roots[i].output_index); } fputs("]}", stream); return true; } bool amduat_format_pel_program(FILE *stream, const amduat_pel_program_t *program, amduat_format_output_t format) { if (stream == NULL || program == NULL) { return false; } if (format == AMDUAT_FORMAT_OUTPUT_TEXT) { return amduat_format_program_text(stream, program); } return amduat_format_program_json(stream, program); } static bool amduat_format_trace_text(FILE *stream, const amduat_pel_trace_dag_value_t *trace, amduat_format_ref_format_t ref_format) { size_t i; fprintf(stream, "pel1_version=%u\n", trace->pel1_version); fprintf(stream, "scheme_ref="); if (!amduat_format_ref_write_text(stream, trace->scheme_ref, ref_format)) { return false; } fputc('\n', stream); fprintf(stream, "program_ref="); if (!amduat_format_ref_write_text(stream, trace->program_ref, ref_format)) { return false; } fputc('\n', stream); fprintf(stream, "status=%s(%u)\n", amduat_format_pel_status_name(trace->status), (unsigned int)trace->status); fprintf(stream, "error_kind=%s(%u)\n", amduat_format_pel_error_kind_name(trace->summary.kind), (unsigned int)trace->summary.kind); fprintf(stream, "status_code=%u\n", (unsigned int)trace->summary.status_code); fprintf(stream, "has_exec_result_ref=%s\n", trace->has_exec_result_ref ? "true" : "false"); if (trace->has_exec_result_ref) { fprintf(stream, "exec_result_ref="); if (!amduat_format_ref_write_text(stream, trace->exec_result_ref, ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "input_refs_len=%zu\n", trace->input_refs_len); for (i = 0; i < trace->input_refs_len; ++i) { fprintf(stream, "input_ref[%zu]=", i); if (!amduat_format_ref_write_text(stream, trace->input_refs[i], ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "has_params_ref=%s\n", trace->has_params_ref ? "true" : "false"); if (trace->has_params_ref) { fprintf(stream, "params_ref="); if (!amduat_format_ref_write_text(stream, trace->params_ref, ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "node_traces_len=%zu\n", trace->node_traces_len); for (i = 0; i < trace->node_traces_len; ++i) { const amduat_pel_node_trace_dag_t *node = &trace->node_traces[i]; size_t j; char prefix[64]; fprintf(stream, "node_trace[%zu].node_id=%u\n", i, node->node_id); fprintf(stream, "node_trace[%zu].op.name=%.*s\n", i, (int)node->op_name.len, node->op_name.data ? (const char *)node->op_name.data : ""); fprintf(stream, "node_trace[%zu].op.version=%u\n", i, node->op_version); fprintf(stream, "node_trace[%zu].status=%s(%u)\n", i, amduat_format_pel_node_status_name(node->status), (unsigned int)node->status); fprintf(stream, "node_trace[%zu].status_code=%u\n", i, node->status_code); fprintf(stream, "node_trace[%zu].output_refs_len=%zu\n", i, node->output_refs_len); for (j = 0; j < node->output_refs_len; ++j) { fprintf(stream, "node_trace[%zu].output_ref[%zu]=", i, j); if (!amduat_format_ref_write_text(stream, node->output_refs[j], ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "node_trace[%zu].diagnostics_len=%zu\n", i, node->diagnostics_len); snprintf(prefix, sizeof(prefix), "node_trace[%zu].", i); if (!amduat_format_diagnostics_text(stream, prefix, node->diagnostics, node->diagnostics_len)) { return false; } } return true; } static bool amduat_format_trace_json(FILE *stream, const amduat_pel_trace_dag_value_t *trace, amduat_format_ref_format_t ref_format) { size_t i; fputs("{\"pel1_version\":", stream); fprintf(stream, "%u", trace->pel1_version); fputs(",\"scheme_ref\":", stream); if (!amduat_format_ref_write_json(stream, trace->scheme_ref, ref_format)) { return false; } fputs(",\"program_ref\":", stream); if (!amduat_format_ref_write_json(stream, trace->program_ref, ref_format)) { return false; } fputs(",\"status\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_status_name(trace->status), strlen(amduat_format_pel_status_name(trace->status))))) { return false; } fprintf(stream, ",\"status_code\":%u", (unsigned int)trace->summary.status_code); fputs(",\"error_kind\":", stream); if (!amduat_format_json_escape( stream, amduat_octets( amduat_format_pel_error_kind_name(trace->summary.kind), strlen(amduat_format_pel_error_kind_name(trace->summary.kind))))) { return false; } fprintf(stream, ",\"error_kind_code\":%u", (unsigned int)trace->summary.kind); fputs(",\"has_exec_result_ref\":", stream); fputs(trace->has_exec_result_ref ? "true" : "false", stream); fputs(",\"exec_result_ref\":", stream); if (trace->has_exec_result_ref) { if (!amduat_format_ref_write_json(stream, trace->exec_result_ref, ref_format)) { return false; } } else { fputs("null", stream); } fputs(",\"input_refs\":[", stream); for (i = 0; i < trace->input_refs_len; ++i) { if (i != 0) { fputc(',', stream); } if (!amduat_format_ref_write_json(stream, trace->input_refs[i], ref_format)) { return false; } } fputs("]", stream); fputs(",\"has_params_ref\":", stream); fputs(trace->has_params_ref ? "true" : "false", stream); fputs(",\"params_ref\":", stream); if (trace->has_params_ref) { if (!amduat_format_ref_write_json(stream, trace->params_ref, ref_format)) { return false; } } else { fputs("null", stream); } fputs(",\"node_traces\":[", stream); for (i = 0; i < trace->node_traces_len; ++i) { const amduat_pel_node_trace_dag_t *node = &trace->node_traces[i]; size_t j; if (i != 0) { fputc(',', stream); } fprintf(stream, "{\"node_id\":%u,", node->node_id); fputs("\"op\":{\"name\":", stream); if (!amduat_format_json_escape(stream, node->op_name)) { return false; } fprintf(stream, ",\"version\":%u},", node->op_version); fputs("\"status\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_node_status_name(node->status), strlen(amduat_format_pel_node_status_name( node->status))))) { return false; } fprintf(stream, ",\"status_code\":%u", node->status_code); fputs(",\"output_refs\":[", stream); for (j = 0; j < node->output_refs_len; ++j) { if (j != 0) { fputc(',', stream); } if (!amduat_format_ref_write_json(stream, node->output_refs[j], ref_format)) { return false; } } fputs("],\"diagnostics\":", stream); if (!amduat_format_diagnostics_json(stream, node->diagnostics, node->diagnostics_len)) { return false; } fputs("}", stream); } fputs("]}", stream); return true; } bool amduat_format_pel_trace(FILE *stream, const amduat_pel_trace_dag_value_t *trace, amduat_format_output_t format, amduat_format_ref_format_t ref_format) { if (stream == NULL || trace == NULL) { return false; } if (format == AMDUAT_FORMAT_OUTPUT_TEXT) { return amduat_format_trace_text(stream, trace, ref_format); } return amduat_format_trace_json(stream, trace, ref_format); } static bool amduat_format_result_text( FILE *stream, const amduat_pel_surface_execution_result_t *result, amduat_format_ref_format_t ref_format) { size_t i; fprintf(stream, "pel1_version=%u\n", result->pel1_version); fprintf(stream, "scheme_ref="); if (!amduat_format_ref_write_text(stream, result->scheme_ref, ref_format)) { return false; } fputc('\n', stream); fprintf(stream, "program_ref="); if (!amduat_format_ref_write_text(stream, result->program_ref, ref_format)) { return false; } fputc('\n', stream); fprintf(stream, "status=%s(%u)\n", amduat_format_pel_status_name(result->core_result.status), (unsigned int)result->core_result.status); fprintf(stream, "error_kind=%s(%u)\n", amduat_format_pel_error_kind_name(result->core_result.summary.kind), (unsigned int)result->core_result.summary.kind); fprintf(stream, "status_code=%u\n", (unsigned int)result->core_result.summary.status_code); if (!amduat_format_diagnostics_text(stream, "", result->core_result.diagnostics, result->core_result.diagnostics_len)) { return false; } fprintf(stream, "input_refs_len=%zu\n", result->input_refs_len); for (i = 0; i < result->input_refs_len; ++i) { fprintf(stream, "input_ref[%zu]=", i); if (!amduat_format_ref_write_text(stream, result->input_refs[i], ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "output_refs_len=%zu\n", result->output_refs_len); for (i = 0; i < result->output_refs_len; ++i) { fprintf(stream, "output_ref[%zu]=", i); if (!amduat_format_ref_write_text(stream, result->output_refs[i], ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "has_params_ref=%s\n", result->has_params_ref ? "true" : "false"); if (result->has_params_ref) { fprintf(stream, "params_ref="); if (!amduat_format_ref_write_text(stream, result->params_ref, ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "has_trace_ref=%s\n", result->has_trace_ref ? "true" : "false"); if (result->has_trace_ref) { fprintf(stream, "trace_ref="); if (!amduat_format_ref_write_text(stream, result->trace_ref, ref_format)) { return false; } fputc('\n', stream); } fprintf(stream, "has_store_failure=%s\n", result->has_store_failure ? "true" : "false"); if (result->has_store_failure) { fprintf(stream, "store_failure.phase=%s(%u)\n", amduat_format_pel_store_phase_name(result->store_failure.phase), (unsigned int)result->store_failure.phase); fprintf(stream, "store_failure.error_code=%s(%u)\n", amduat_format_pel_store_error_name( result->store_failure.error_code), (unsigned int)result->store_failure.error_code); fprintf(stream, "store_failure.failing_ref="); if (!amduat_format_ref_write_text( stream, result->store_failure.failing_ref, ref_format)) { return false; } fputc('\n', stream); } return true; } static bool amduat_format_result_json( FILE *stream, const amduat_pel_surface_execution_result_t *result, amduat_format_ref_format_t ref_format) { size_t i; fputs("{\"pel1_version\":", stream); fprintf(stream, "%u", result->pel1_version); fputs(",\"scheme_ref\":", stream); if (!amduat_format_ref_write_json(stream, result->scheme_ref, ref_format)) { return false; } fputs(",\"program_ref\":", stream); if (!amduat_format_ref_write_json(stream, result->program_ref, ref_format)) { return false; } fputs(",\"status\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_status_name( result->core_result.status), strlen(amduat_format_pel_status_name( result->core_result.status))))) { return false; } fprintf(stream, ",\"status_code\":%u", (unsigned int)result->core_result.summary.status_code); fputs(",\"error_kind\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_error_kind_name( result->core_result.summary.kind), strlen(amduat_format_pel_error_kind_name( result->core_result.summary.kind))))) { return false; } fprintf(stream, ",\"error_kind_code\":%u", (unsigned int)result->core_result.summary.kind); fputs(",\"diagnostics\":", stream); if (!amduat_format_diagnostics_json( stream, result->core_result.diagnostics, result->core_result.diagnostics_len)) { return false; } fputs(",\"input_refs\":[", stream); for (i = 0; i < result->input_refs_len; ++i) { if (i != 0) { fputc(',', stream); } if (!amduat_format_ref_write_json(stream, result->input_refs[i], ref_format)) { return false; } } fputs("]", stream); fputs(",\"output_refs\":[", stream); for (i = 0; i < result->output_refs_len; ++i) { if (i != 0) { fputc(',', stream); } if (!amduat_format_ref_write_json(stream, result->output_refs[i], ref_format)) { return false; } } fputs("]", stream); fputs(",\"has_params_ref\":", stream); fputs(result->has_params_ref ? "true" : "false", stream); fputs(",\"params_ref\":", stream); if (result->has_params_ref) { if (!amduat_format_ref_write_json(stream, result->params_ref, ref_format)) { return false; } } else { fputs("null", stream); } fputs(",\"has_trace_ref\":", stream); fputs(result->has_trace_ref ? "true" : "false", stream); fputs(",\"trace_ref\":", stream); if (result->has_trace_ref) { if (!amduat_format_ref_write_json(stream, result->trace_ref, ref_format)) { return false; } } else { fputs("null", stream); } fputs(",\"has_store_failure\":", stream); fputs(result->has_store_failure ? "true" : "false", stream); fputs(",\"store_failure\":", stream); if (result->has_store_failure) { fputs("{\"phase\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_store_phase_name( result->store_failure.phase), strlen(amduat_format_pel_store_phase_name( result->store_failure.phase))))) { return false; } fprintf(stream, ",\"phase_code\":%u", (unsigned int)result->store_failure.phase); fputs(",\"error_code\":", stream); if (!amduat_format_json_escape( stream, amduat_octets(amduat_format_pel_store_error_name( result->store_failure.error_code), strlen(amduat_format_pel_store_error_name( result->store_failure.error_code))))) { return false; } fprintf(stream, ",\"error_code_id\":%u", (unsigned int)result->store_failure.error_code); fputs(",\"failing_ref\":", stream); if (!amduat_format_ref_write_json(stream, result->store_failure.failing_ref, ref_format)) { return false; } fputs("}", stream); } else { fputs("null", stream); } fputs("}", stream); return true; } bool amduat_format_pel_result(FILE *stream, const amduat_pel_surface_execution_result_t *result, amduat_format_output_t format, amduat_format_ref_format_t ref_format) { if (stream == NULL || result == NULL) { return false; } if (format == AMDUAT_FORMAT_OUTPUT_TEXT) { return amduat_format_result_text(stream, result, ref_format); } return amduat_format_result_json(stream, result, ref_format); }