blob: 9bcf2c907832b238c214024d2a820564dd859a10 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*!
* \file tvm/target/parsers/mprofile.cc
* \brief Target Parser for Arm(R) Cortex(R) M-Profile CPUs
*/
#include "mprofile.h"
#include <string>
namespace tvm {
namespace target {
namespace parsers {
namespace mprofile {
const TargetFeatures kNoExt = {{"has_dsp", Bool(false)}, {"has_mve", Bool(false)}};
const TargetFeatures kHasDSP = {{"has_dsp", Bool(true)}, {"has_mve", Bool(false)}};
const TargetFeatures kHasMVE = {{"has_dsp", Bool(true)}, {"has_mve", Bool(true)}};
static const char* baseCPUs[] = {"cortex-m0", "cortex-m3"};
static const char* dspCPUs[] = {"cortex-m55", "cortex-m4", "cortex-m7", "cortex-m33",
"cortex-m35p"};
static const char* mveCPUs[] = {"cortex-m55"};
template <typename Container>
static inline bool MatchesCpu(Optional<String> mcpu, const Container& cpus) {
if (!mcpu) {
return false;
}
std::string mcpu_string = mcpu.value();
auto matches_cpu = [mcpu_string](const char* cpu) { return mcpu_string.find(cpu) == 0; };
return std::find_if(std::begin(cpus), std::end(cpus), matches_cpu) != std::end(cpus);
}
static inline bool HasFlag(String attr, std::string flag) {
std::string attr_str = attr;
return attr_str.find(flag) != std::string::npos;
}
static inline bool HasFlag(Optional<String> attr, std::string flag) {
if (!attr) {
return false;
}
return HasFlag(attr.value(), flag);
}
static inline bool HasFlag(Optional<Array<String>> attr, std::string flag) {
if (!attr) {
return false;
}
Array<String> attr_array = attr.value();
auto matching_attr = std::find_if(attr_array.begin(), attr_array.end(),
[flag](String attr_str) { return HasFlag(attr_str, flag); });
return matching_attr != attr_array.end();
}
bool IsArch(TargetJSON attrs) {
Optional<String> mcpu = Downcast<Optional<String>>(attrs.Get("mcpu"));
if (mcpu) {
bool matches_base = MatchesCpu(mcpu, baseCPUs);
bool matches_dsp = MatchesCpu(mcpu, dspCPUs);
bool matches_mve = MatchesCpu(mcpu, mveCPUs);
return matches_base || matches_mve || matches_dsp;
}
return false;
}
static TargetFeatures GetFeatures(TargetJSON target) {
Optional<String> mcpu = Downcast<Optional<String>>(target.Get("mcpu"));
Optional<Array<String>> mattr = Downcast<Optional<Array<String>>>(target.Get("mattr"));
bool nomve = HasFlag(mcpu, "+nomve") || HasFlag(mattr, "+nomve");
bool nodsp = HasFlag(mcpu, "+nodsp") || HasFlag(mattr, "+nodsp");
bool has_mve = MatchesCpu(mcpu, mveCPUs);
if (has_mve && !nomve && !nodsp) {
return kHasMVE;
}
bool has_dsp = MatchesCpu(mcpu, dspCPUs);
if (has_dsp && !nodsp) {
return kHasDSP;
}
return kNoExt;
}
static Array<String> MergeKeys(Optional<Array<String>> existing_keys) {
const Array<String> kExtraKeys = {"arm_cpu", "cpu"};
if (!existing_keys) {
return kExtraKeys;
}
Array<String> keys = existing_keys.value();
for (String key : kExtraKeys) {
if (std::find(keys.begin(), keys.end(), key) == keys.end()) {
keys.push_back(key);
}
}
return keys;
}
TargetJSON ParseTarget(TargetJSON target) {
target.Set("features", GetFeatures(target));
target.Set("keys", MergeKeys(Downcast<Optional<Array<String>>>(target.Get("keys"))));
return target;
}
} // namespace mprofile
} // namespace parsers
} // namespace target
} // namespace tvm