--- /dev/null
+/**
+ * Proprietary
+ * Copyright (C) 2020 Samsung Electronics
+ * Copyright (C) 2020 Dongju Chae <dongju.chae@samsung.com>
+ */
+/**
+ * @file model-inspect.cc
+ * @date 20 Aug 2020
+ * @brief Utility to inspect trinity model files
+ * @author Dongju Chae <dongju.chae@samsung.com>
+ * @bug No known bugs except for NYI items
+ */
+
+#include <libnpuhost.h>
+#include <npubinfmt.h>
+
+#include <iostream>
+#include <fstream>
+
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+class Inspector {
+ public:
+ Inspector ();
+ ~Inspector ();
+
+ int init (std::string model);
+ int run ();
+
+ void set_dump_meta () { dump_meta_ = true; }
+ void set_dump_program () { dump_program_ = true; }
+ void set_dump_weight () { dump_weight_ = true; }
+ void set_output_dir (std::string output) { dump_output_ = output; }
+
+ private:
+ void dump ();
+ int show ();
+
+ void show_common ();
+ void show_v1 ();
+ void show_v2 ();
+ void show_v3 ();
+
+ npubin_meta * meta_;
+ std::ifstream ifs_;
+
+ std::string dump_output_;
+
+ bool dump_meta_;
+ bool dump_program_;
+ bool dump_weight_;
+};
+
+Inspector::Inspector ()
+{
+ meta_ = nullptr;
+ dump_meta_ = false;
+ dump_program_ = false;
+ dump_weight_ = false;
+}
+
+Inspector::~Inspector ()
+{
+ if (meta_ != nullptr)
+ free (meta_);
+}
+
+int Inspector::init (std::string model)
+{
+ std::cerr << "Inspecting model binary: " << model << "\n\n";
+
+ ifs_.open (model, std::ios::binary);
+ if (ifs_.fail ()) {
+ std::cerr << strerror (errno) << "\n";
+ return -errno;
+ }
+
+ meta_ = (npubin_meta *) malloc (NPUBIN_META_SIZE);
+ if (meta_ == nullptr) {
+ std::cerr << strerror (errno) << "\n";
+ return -errno;
+ }
+
+ ifs_.read (reinterpret_cast<char*>(meta_), NPUBIN_META_SIZE);
+ if (!CHECK_NPUBIN (meta_->magiccode)) {
+ std::cerr << "Non-compatible binary format\n";
+ return -EINVAL;
+ }
+
+ if (dump_output_ == "")
+ dump_output_ = ".";
+
+ if (access (dump_output_.c_str (), W_OK) != 0) {
+ std::cerr << "The given output directory (" << dump_output_ << ") "
+ << "doesn't have write permission\n";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int Inspector::run ()
+{
+ int status = show ();
+
+ if (status == 0)
+ dump ();
+
+ return status;
+}
+
+int Inspector::show ()
+{
+ uint64_t version = NPUBIN_VERSION (meta_->magiccode);
+
+ switch (version) {
+ case 0:
+ // no-break;
+ case 1:
+ show_v1 ();
+ break;
+ case 2:
+ show_v2 ();
+ break;
+ case 3:
+ show_v3 ();
+ break;
+ default:
+ std::cerr << "Unsupported npubinfmt version: " << version << "\n";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void Inspector::show_common ()
+{
+ std::cout << "[common] " << "\n";
+ std::cout << " model format: " << NPUBIN_VERSION (meta_->magiccode) << "\n";
+ std::cout << " model size: " << meta_->size << "\n";
+ std::cout << " - metadata size: " << NPUBIN_META_TOTAL_SIZE (meta_->magiccode) << "\n";
+ std::cout << " - program size: " << meta_->program_size << "\n";
+ std::cout << " - weight size: " << meta_->weight_size << "\n";
+ std::cout << "\n";
+ std::cout << std::hex;
+ std::cout << " magiccode: 0x" << meta_->magiccode << "\n";
+ std::cout << " npu_version: 0x" << meta_->npu_version << "\n";
+ std::cout << " compiler_version: 0x" << meta_->compiler_version << "\n";
+ std::cout << "\n";
+}
+
+void Inspector::show_v1 ()
+{
+ show_common ();
+
+ std::cout << "[npubinfmt v1] " << "\n";
+ std::cout << std::dec;
+ std::cout << " buffer_size: " << meta_->buffer_size << "\n";
+ std::cout << " input_offset: " << meta_->input_offset << "\n";
+ std::cout << " input_size: " << meta_->input_size << "\n";
+ std::cout << " output_offset: " << meta_->output_offset << "\n";
+ std::cout << " output_size: " << meta_->output_size << "\n";
+}
+
+void Inspector::show_v2 ()
+{
+ show_common ();
+
+ std::cout << "[npubinfmt v2] " << "\n";
+ std::cout << std::dec;
+ std::cout << " input_num: " << meta_->input_num << "\n";
+ for (uint32_t i = 0; i < meta_->input_num; i++) {
+ std::cout << std::dec;
+ std::cout << " input_offsets[" << i << "]: " << meta_->input_offsets[i] << "\n";
+ std::cout << " input_elem_size[" << i << "]: " << meta_->input_elem_size[i] << "\n";
+ for (uint32_t j = 0; j < MAX_RANK; j++)
+ std::cout << " input_dims[" << i << "][" << j << "]: " << meta_->input_dims[i][j] << "\n";
+ std::cout << " input_emod_y[" << i << "]: " << meta_->input_emod_y[i] << "\n";
+ std::cout << " input_emod_z[" << i << "]: " << meta_->input_emod_z[i] << "\n";
+ std::cout << " input_quant_z[" << i << "]: " << meta_->input_quant_z[i] << "\n";
+ std::cout << std::fixed;
+ std::cout << " input_quant_s[" << i << "]: " << meta_->input_quant_s[i] << "\n";
+ }
+ std::cout << std::dec << "\n";
+ std::cout << " output_num: " << meta_->output_num << "\n";
+ for (uint32_t i = 0; i < meta_->output_num; i++) {
+ std::cout << std::dec;
+ std::cout << " output_offsets[" << i << "]: " << meta_->output_offsets[i] << "\n";
+ std::cout << " output_elem_size[" << i << "]: " << meta_->output_elem_size[i] << "\n";
+ for (uint32_t j = 0; j < MAX_RANK; j++)
+ std::cout << " output_dims[" << i << "][" << j << "]: " << meta_->output_dims[i][j] << "\n";
+ std::cout << " output_emod_y[" << i << "]: " << meta_->output_emod_y[i] << "\n";
+ std::cout << " output_emod_z[" << i << "]: " << meta_->output_emod_z[i] << "\n";
+ std::cout << " output_quant_z[" << i << "]: " << meta_->output_quant_z[i] << "\n";
+ std::cout << std::fixed;
+ std::cout << " output_quant_s[" << i << "]: " << meta_->output_quant_s[i] << "\n";
+ }
+}
+
+void Inspector::show_v3 ()
+{
+ show_common ();
+
+ std::cout << "[npubinfmt v2] " << "\n";
+ std::cout << std::dec;
+ std::cout << " segment_num: " << meta_->segment_num << "\n";
+ for (uint32_t i = 0; i < meta_->segment_num; i++) {
+ std::cout << " segment_size[" << i << "]: " << meta_->segment_size[i] << "\n";
+ }
+ std::cout << "\n";
+ std::cout << " weight_seg_idx: " << meta_->weight_seg_idx << "\n";
+ std::cout << "\n";
+ std::cout << " input_seg_num: " << meta_->input_seg_num << "\n";
+ for (uint32_t i = 0; i < meta_->input_seg_num; i++) {
+ std::cout << std::dec;
+ std::cout << " input_seg_idx[" << i << "]: " << meta_->input_seg_idx[i] << "\n";
+ std::cout << " input_seg_off[" << i << "]: " << meta_->input_seg_off[i] << "\n";
+ for (uint32_t j = 0; j < MAX_RANK; j++)
+ std::cout << " input_seg_dims[" << i << "][" << j << "]: " << meta_->input_seg_dims[i][j] << "\n";
+ std::cout << " input_seg_emod_y[" << i << "]: " << meta_->input_seg_emod_y[i] << "\n";
+ std::cout << " input_seg_emod_z[" << i << "]: " << meta_->input_seg_emod_z[i] << "\n";
+ std::cout << " input_seg_quant_type[" << i << "]: " << meta_->input_seg_quant_type[i] << "\n";
+ std::cout << " input_seg_quant_z[" << i << "]: " << meta_->input_seg_quant_z[i] << "\n";
+ std::cout << std::fixed;
+ std::cout << " input_seg_quant_s[" << i << "]: " << meta_->input_seg_quant_s[i] << "\n";
+ }
+ std::cout << std::dec << "\n";
+ std::cout << " output_seg_num: " << meta_->output_seg_num << "\n";
+ for (uint32_t i = 0; i < meta_->output_seg_num; i++) {
+ std::cout << std::dec;
+ std::cout << " output_seg_idx[" << i << "]: " << meta_->output_seg_idx[i] << "\n";
+ std::cout << " output_seg_off[" << i << "]: " << meta_->output_seg_off[i] << "\n";
+ for (uint32_t j = 0; j < MAX_RANK; j++)
+ std::cout << " output_seg_dims[" << i << "][" << j << "]: " << meta_->output_seg_dims[i][j] << "\n";
+ std::cout << " output_seg_emod_y[" << i << "]: " << meta_->output_seg_emod_y[i] << "\n";
+ std::cout << " output_seg_emod_z[" << i << "]: " << meta_->output_seg_emod_z[i] << "\n";
+ std::cout << " output_seg_quant_type[" << i << "]: " << meta_->output_seg_quant_type[i] << "\n";
+ std::cout << " output_seg_quant_z[" << i << "]: " << meta_->output_seg_quant_z[i] << "\n";
+ std::cout << std::fixed;
+ std::cout << " output_seg_quant_s[" << i << "]: " << meta_->output_seg_quant_s[i] << "\n";
+ }
+}
+
+void Inspector::dump ()
+{
+ size_t size_metadata = NPUBIN_META_TOTAL_SIZE (meta_->magiccode);
+
+ if (dump_meta_) {
+ std::ofstream ofs (dump_output_ + "/metadata.bin", std::ios::binary);
+ if (ofs.good ()) {
+ char * buf = new char [size_metadata];
+
+ ifs_.seekg (0);
+ ifs_.read (buf, size_metadata);
+ ofs.write (buf, size_metadata);
+
+ delete [] buf;
+ }
+ }
+
+ if (dump_program_) {
+ std::ofstream ofs (dump_output_ + "/program.bin", std::ios::binary);
+ if (ofs.good ()) {
+ char * buf = new char [meta_->program_size];
+
+ ifs_.seekg (size_metadata);
+ ifs_.read (buf, meta_->program_size);
+ ofs.write (buf, meta_->program_size);
+
+ delete [] buf;
+ }
+ }
+
+ if (dump_weight_) {
+ std::ofstream ofs (dump_output_ + "/weight.bin", std::ios::binary);
+ if (ofs.good ()) {
+ char * buf = new char [meta_->weight_size];
+
+ ifs_.seekg (size_metadata + meta_->program_size);
+ ifs_.read (buf, meta_->weight_size);
+ ofs.write (buf, meta_->weight_size);
+
+ delete [] buf;
+ }
+ }
+}
+
+static void
+print_usage (const char *prog_name)
+{
+ std::cerr << "Usage: " << prog_name << " [options] model_path\n";
+ std::cerr << "Options: \n";
+ std::cerr << " -o <arg> \t Set output directory\n";
+ std::cerr << " -m \t\t Extract metadata section\n";
+ std::cerr << " -p \t\t Extract program section\n";
+ std::cerr << " -w \t\t Extract weight section\n";
+}
+
+int main (int argc, char **argv)
+{
+ Inspector inspector;
+ int c, status = 0;
+
+ optind = 0;
+ opterr = 0;
+ while ((c = getopt (argc, argv, "mpwho:")) != -1) {
+ switch (c) {
+ case 'm':
+ inspector.set_dump_meta ();
+ break;
+ case 'p':
+ inspector.set_dump_program ();
+ break;
+ case 'w':
+ inspector.set_dump_weight ();
+ break;
+ case 'o':
+ inspector.set_output_dir (optarg);
+ break;
+ case '?':
+ if (optopt == 'o')
+ std::cerr << "Option -o requires an extra argument";
+ else
+ std::cerr << "Unknown flag: " << c;
+ std::cerr << std::endl;
+ status = -EINVAL;
+ // no-break
+ case 'h':
+ print_usage (argv[0]);
+ return status;
+ }
+ }
+
+ if (optind >= argc) {
+ std::cerr << "Please provide model binary path\n\n";
+ print_usage (argv[0]);
+ return -EINVAL;
+ }
+
+ status = inspector.init (argv[optind]);
+ if (status != 0)
+ return status;
+
+ return inspector.run ();
+}