diff --git a/compiler/circle-inspect/driver/Driver.cpp b/compiler/circle-inspect/driver/Driver.cpp index 6371261db87..465f4171824 100644 --- a/compiler/circle-inspect/driver/Driver.cpp +++ b/compiler/circle-inspect/driver/Driver.cpp @@ -37,6 +37,7 @@ int entry(int argc, char **argv) arser.add_argument("--constants").nargs(0).help("Dump constant tensors name"); arser.add_argument("--op_version").nargs(0).help("Dump versions of the operators in circle file"); arser.add_argument("--tensor_dtype").nargs(0).help("Dump dtype of tensors"); + arser.add_argument("--tensor_shape").nargs(0).help("Dump shape of tensors"); arser.add_argument("circle").help("Circle file to inspect"); try @@ -51,7 +52,7 @@ int entry(int argc, char **argv) } if (!arser["--operators"] && !arser["--conv2d_weight"] && !arser["--op_version"] && - !arser["--tensor_dtype"] && !arser["--constants"]) + !arser["--tensor_dtype"] && !arser["--constants"] && !arser["--tensor_shape"]) { std::cout << "At least one option must be specified" << std::endl; std::cout << arser; @@ -70,6 +71,8 @@ int entry(int argc, char **argv) dumps.push_back(std::make_unique()); if (arser["--constants"]) dumps.push_back(std::make_unique()); + if (arser["--tensor_shape"]) + dumps.push_back(std::make_unique()); std::string model_file = arser.get("circle"); diff --git a/compiler/circle-inspect/src/Dump.cpp b/compiler/circle-inspect/src/Dump.cpp index 9d363e1ffa9..aa1f0673274 100644 --- a/compiler/circle-inspect/src/Dump.cpp +++ b/compiler/circle-inspect/src/Dump.cpp @@ -240,3 +240,34 @@ void DumpConstants::run(std::ostream &os, const circle::Model *model, const std: } } // namespace circleinspect + +namespace circleinspect +{ + +void DumpTensorShape::run(std::ostream &os, const circle::Model *model, + const std::vector *data) +{ + mio::circle::Reader reader(model, data); + + const uint32_t subgraph_size = reader.num_subgraph(); + + for (uint32_t g = 0; g < subgraph_size; g++) + { + reader.select_subgraph(g); + auto tensors = reader.tensors(); + + for (uint32_t i = 0; i < tensors->size(); ++i) + { + const auto tensor = tensors->Get(i); + auto shape = tensor->shape_signature() ? tensor->shape_signature() : tensor->shape(); + os << reader.tensor_name(tensor) << " "; + for (int8_t i = 0; i < shape->size(); i++) + { + os << shape->Get(i); + } + os << std::endl; + } + } +} + +} // namespace circleinspect diff --git a/compiler/circle-inspect/src/Dump.h b/compiler/circle-inspect/src/Dump.h index 12a43a71001..4959adcf1db 100644 --- a/compiler/circle-inspect/src/Dump.h +++ b/compiler/circle-inspect/src/Dump.h @@ -78,6 +78,15 @@ class DumpConstants final : public DumpInterface void run(std::ostream &os, const circle::Model *model, const std::vector *data); }; +class DumpTensorShape final : public DumpInterface +{ +public: + DumpTensorShape() = default; + +public: + void run(std::ostream &os, const circle::Model *model, const std::vector *data); +}; + } // namespace circleinspect #endif // __DUMP_H__ diff --git a/compiler/dredd-rule-lib/rule-lib.sh b/compiler/dredd-rule-lib/rule-lib.sh index a920e08abc1..3ee94e6881b 100755 --- a/compiler/dredd-rule-lib/rule-lib.sh +++ b/compiler/dredd-rule-lib/rule-lib.sh @@ -252,4 +252,21 @@ const_count() echo ${ACTUAL} } +tensor_shape() +{ + argc_check $# 1 + file_path_check ${COMPILED_FILE} + file_path_check ${INSPECT_PROG_PATH} + + set -o pipefail + + ACTUAL=`init_error_log ; \ + ${INSPECT_PROG_PATH} --tensor_shape ${COMPILED_FILE} | \ + awk -v tensor_name="$1" '{ if ($1 == tensor_name) print $2}'` + + check_success_exit_code $? 0 + + echo ${ACTUAL} +} + # TODO define more qullity test function diff --git a/res/TensorFlowLiteRecipes/Pad_002/test.recipe b/res/TensorFlowLiteRecipes/Pad_002/test.recipe new file mode 100644 index 00000000000..3e4ba359bf1 --- /dev/null +++ b/res/TensorFlowLiteRecipes/Pad_002/test.recipe @@ -0,0 +1,33 @@ +# padding with dynamic shape, others same as Pad_000 +operand { + name: "ifm" + type: FLOAT32 + shape { dim: 1 dim: 3 dim: 3 dim: 2 } + shape_signature { dim: -1 dim: 3 dim: 3 dim: 2 } +} +operand { + name: "padding" + type: INT64 + shape { dim: 4 dim: 2 } + filler { + tag: "explicit" + arg: "0" arg: "0" + arg: "1" arg: "1" + arg: "2" arg: "2" + arg: "0" arg: "0" + } +} +operand { + name: "ofm" + type: FLOAT32 + shape { dim: 1 dim: 5 dim: 7 dim: 2 } + shape_signature { dim: -1 dim: 5 dim: 7 dim: 2 } +} +operation { + type: "Pad" + input: "ifm" + input: "padding" + output: "ofm" +} +input: "ifm" +output: "ofm" diff --git a/res/TensorFlowLiteRecipes/Pad_002/test.rule b/res/TensorFlowLiteRecipes/Pad_002/test.rule new file mode 100644 index 00000000000..08d53a1d691 --- /dev/null +++ b/res/TensorFlowLiteRecipes/Pad_002/test.rule @@ -0,0 +1,6 @@ +# To check if dynamic dimension properly infered + +RULE "VERIFY_FILE_FORMAT" $(verify_file_format) '=' 1 + +RULE "PAD_EXIST" $(op_count PAD) '=' 1 +RULE "PAD_SHAPE" $(tensor_shape ofm) '=' -1572