comaniac commented on a change in pull request #6218:
URL: https://github.com/apache/incubator-tvm/pull/6218#discussion_r470828288



##########
File path: src/target/target.cc
##########
@@ -162,14 +314,164 @@ Target Target::Create(const String& target_str) {
   return CreateTarget(splits[0], {splits.begin() + 1, splits.end()});
 }
 
+ObjectRef TargetNode::ParseAttr(const ObjectRef& obj,
+                                const TargetKindNode::ValueTypeInfo& info) 
const {
+  if (info.type_index == 
Integer::ContainerType::_GetOrAllocRuntimeTypeIndex()) {
+    const auto* v = obj.as<IntImmNode>();
+    CHECK(v != nullptr) << "Expect type 'int', but get: " << obj->GetTypeKey();
+    return GetRef<Integer>(v);
+  }
+  if (info.type_index == String::ContainerType::_GetOrAllocRuntimeTypeIndex()) 
{
+    const auto* v = obj.as<StringObj>();
+    CHECK(v != nullptr) << "Expect type 'str', but get: " << obj->GetTypeKey();
+    return GetRef<String>(v);
+  }
+  if (info.type_index == Target::ContainerType::_GetOrAllocRuntimeTypeIndex()) 
{
+    CHECK(obj->IsInstance<MapNode>())
+        << "Expect type 'dict' to construct Target, but get: " << 
obj->GetTypeKey();
+    return Target::FromConfig(Downcast<Map<String, ObjectRef>>(obj));
+  }
+  if (info.type_index == ArrayNode::_GetOrAllocRuntimeTypeIndex()) {
+    CHECK(obj->IsInstance<ArrayNode>()) << "Expect type 'list', but get: " << 
obj->GetTypeKey();
+    Array<ObjectRef> array = Downcast<Array<ObjectRef>>(obj);
+    std::vector<ObjectRef> result;
+    int i = 0;
+    for (const ObjectRef& e : array) {
+      ++i;
+      try {
+        result.push_back(TargetNode::ParseAttr(e, *info.key));
+      } catch (const dmlc::Error& e) {
+        LOG(FATAL) << "Error occurred when parsing element " << i << " of the 
array: " << array
+                   << ". Details:\n"
+                   << e.what();
+      }
+    }
+    return Array<ObjectRef>(result);
+  }
+  if (info.type_index == MapNode::_GetOrAllocRuntimeTypeIndex()) {
+    CHECK(obj->IsInstance<MapNode>()) << "Expect type 'dict', but get: " << 
obj->GetTypeKey();
+    std::unordered_map<ObjectRef, ObjectRef, ObjectHash, ObjectEqual> result;
+    for (const auto& kv : Downcast<Map<ObjectRef, ObjectRef>>(obj)) {
+      ObjectRef key, val;
+      try {
+        key = TargetNode::ParseAttr(kv.first, *info.key);
+      } catch (const tvm::Error& e) {
+        LOG(FATAL) << "Error occurred when parsing a key of the dict: " << 
kv.first
+                   << ". Details:\n"
+                   << e.what();
+      }
+      try {
+        val = TargetNode::ParseAttr(kv.second, *info.val);
+      } catch (const tvm::Error& e) {
+        LOG(FATAL) << "Error occurred when parsing a value of the dict: " << 
kv.second
+                   << ". Details:\n"
+                   << e.what();
+      }
+      result[key] = val;
+    }
+    return Map<ObjectRef, ObjectRef>(result);
+  }
+  LOG(FATAL) << "Unsupported type registered: \"" << info.type_key
+             << "\", and the type given is: " << obj->GetTypeKey();
+  throw;
+}
+
+Target Target::FromConfig(const Map<String, ObjectRef>& config_dict) {
+  const String kKind = "kind";
+  const String kTag = "tag";
+  const String kKeys = "keys";
+  std::unordered_map<std::string, ObjectRef> config(config_dict.begin(), 
config_dict.end());
+  ObjectPtr<TargetNode> target = make_object<TargetNode>();
+  // parse 'kind'
+  if (config.count(kKind)) {
+    const auto* kind = config[kKind].as<StringObj>();
+    CHECK(kind != nullptr) << "AttributeError: Expect type of field 'kind' is 
string, but get: "
+                           << config[kKind]->GetTypeKey();
+    target->kind = TargetKind::Get(GetRef<String>(kind));
+    config.erase(kKind);
+  } else {
+    LOG(FATAL) << "AttributeError: Field 'kind' is not found";
+  }
+  // parse "tag"
+  if (config.count(kTag)) {
+    const auto* tag = config[kTag].as<StringObj>();
+    CHECK(tag != nullptr) << "AttributeError: Expect type of field 'tag' is 
string, but get: "
+                          << config[kTag]->GetTypeKey();
+    target->tag = GetRef<String>(tag);
+    config.erase(kTag);
+  } else {
+    target->tag = "";
+  }
+  // parse "keys"
+  if (config.count(kKeys)) {
+    std::vector<String> keys;
+    // user provided keys
+    const auto* cfg_keys = config[kKeys].as<ArrayNode>();
+    CHECK(cfg_keys != nullptr)
+        << "AttributeError: Expect type of field 'keys' is an Array, but get: "
+        << config[kTag]->GetTypeKey();
+    for (const ObjectRef& e : *cfg_keys) {
+      const auto* key = e.as<StringObj>();
+      CHECK(key != nullptr) << "AttributeError: Expect 'keys' to be an array 
of strings, but it "
+                               "contains an element of type: "
+                            << e->GetTypeKey();
+      keys.push_back(GetRef<String>(key));
+    }
+    // add device name
+    if (config_dict.count("device") && 
config_dict.at("device")->IsInstance<StringObj>()) {
+      keys.push_back(Downcast<String>(config_dict.at("device")));
+    }
+    // add default keys
+    for (const auto& key : target->kind->default_keys) {
+      keys.push_back(key);
+    }
+    // de-duplicate keys
+    target->keys = DeduplicateKeys(keys);

Review comment:
       Fair enough. Then I would just have 3 points accordingly:
   - We don't aim to have a comprehensive semantic checking in the target 
parser. Instead, we only insist the basic semantic for users that do not want 
to spend time on investigating how target should be set. For example, `{"kind": 
"llvm"}` for X86, `{"kind": "llvm", "device": "arm_cpu"}` for ARM.
   - Assuming the error handling that the community is working on would be 
mature shortly, the target with incorrect semantic should be caught somewhere 
in the build pipeline and a proper error message will be delivered to users.
   - As I mentioned before in the online meetup, we really need a document to 
teach everyone how to set up a proper target to fit the environment. We should 
open an issue to track the progress of this series of target updating and 
documentation sould be the last step.
   




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to