Skip to content

Commit af2c644

Browse files
authored
[projmgr] MLOps: make it tolerant to missing hardware or simulator targets
1 parent e673230 commit af2c644

8 files changed

Lines changed: 175 additions & 93 deletions

File tree

tools/projmgr/include/ProjMgrMlops.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "ProjMgrWorker.h"
1111

12+
#include <optional>
13+
1214
struct CsolutionItem;
1315
struct ContextItem;
1416
struct CustomItem;
@@ -126,8 +128,10 @@ class ProjMgrMlops {
126128
private:
127129
ProjMgrWorker* m_worker = nullptr;
128130
bool FindTargetType(const CsolutionItem& csolution, const std::string& typeName, TargetType& targetType) const;
129-
bool GetTargetSetItemRef(const TargetType& targetType, const std::string& targetTypeName,
130-
const std::string& targetSetName, bool simulatorDefault, TargetSetItem& targetSet) const;
131+
bool ResolveTargetSet(const CsolutionItem& csolution, const MlopsTargetItem target,
132+
bool simulatorDefault, std::string& typeName, TargetSetItem& targetSetItem) const;
133+
bool GetTargetSetItemRef(const TargetType& targetType, std::optional<const std::string> targetSetName,
134+
bool simulatorDefault, TargetSetItem& targetSet) const;
131135
std::string BuildActive(const std::string& targetType, const std::string& targetSet) const;
132136
std::string GetCustomScalar(const CustomItem& custom, const std::string& key) const;
133137
std::string BuildVelaOptions(const MlopsNpuType& npu, const MlopsVelaItem& vela) const;

tools/projmgr/src/ProjMgrMlops.cpp

Lines changed: 99 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -27,40 +27,64 @@ bool ProjMgrMlops::FindTargetType(const CsolutionItem& csolution, const string&
2727
return true;
2828
}
2929
}
30-
ProjMgrLogger::Get().Error("mlops: target-type '" + typeName + "' not found");
3130
return false;
3231
}
3332

34-
bool ProjMgrMlops::GetTargetSetItemRef(const TargetType& targetType, const string& targetTypeName,
35-
const string& targetSetName, bool simulatorDefault, TargetSetItem& targetSet) const {
36-
if (targetSetName.empty()) {
37-
if (simulatorDefault) {
38-
for (const auto& set : targetType.targetSet) {
39-
if (set.debugger.name == "Arm-FVP") {
40-
targetSet = set;
41-
return true;
42-
}
33+
bool ProjMgrMlops::GetTargetSetItemRef(const TargetType& targetType, optional<const string> targetSetName,
34+
bool simulator, TargetSetItem& targetSet) const {
35+
if (!targetSetName.has_value()) {
36+
for (const auto& set : targetType.targetSet) {
37+
if ((simulator && set.debugger.name == "Arm-FVP") ||
38+
(!simulator && set.debugger.name != "Arm-FVP")) {
39+
// default simulator or hardware target set
40+
targetSet = set;
41+
return true;
4342
}
44-
ProjMgrLogger::Get().Error("mlops: simulator target with debugger 'Arm-FVP' not found");
45-
return false;
46-
}
47-
if (!targetType.targetSet.empty()) {
48-
targetSet = targetType.targetSet.front();
49-
return true;
5043
}
5144
} else {
5245
for (const auto& set : targetType.targetSet) {
53-
if (set.set == targetSetName) {
46+
if (set.set == targetSetName.value()) {
47+
// specified target set
5448
targetSet = set;
5549
return true;
5650
}
5751
}
5852
}
59-
ProjMgrLogger::Get().Error("mlops: target-type '" + targetTypeName + "' target-set '" +
60-
(targetSetName.empty() ? "<default>" : targetSetName) + "' not found");
53+
// target set could not be determined
6154
return false;
6255
}
6356

57+
bool ProjMgrMlops::ResolveTargetSet(const CsolutionItem& csolution, const MlopsTargetItem target,
58+
bool simulatorDefault, string& typeName, TargetSetItem& targetSetItem) const {
59+
TargetType targetType;
60+
if (target.targetType.empty()) {
61+
if (!csolution.targetTypes.empty()) {
62+
// default simulator: last target-type, default hardware: first target-type
63+
typeName = simulatorDefault ? csolution.targetTypes.back().first : csolution.targetTypes.front().first;
64+
targetType = simulatorDefault ? csolution.targetTypes.back().second : csolution.targetTypes.front().second;
65+
}
66+
} else {
67+
typeName = target.targetType;
68+
if (!FindTargetType(csolution, target.targetType, targetType)) {
69+
// print error if specified target type was not found
70+
ProjMgrLogger::Get().Error("mlops: target type '" + target.targetType + "' not found");
71+
return false;
72+
}
73+
}
74+
// target set name = nullopt if target type is not specified, to differentiate from default (unnamed) target set
75+
auto targetSetName = target.targetType.empty() ? nullopt : make_optional(target.targetSet);
76+
if (!GetTargetSetItemRef(targetType, targetSetName, simulatorDefault, targetSetItem)) {
77+
if (targetSetName.has_value()) {
78+
// print error if specified target set was not found
79+
ProjMgrLogger::Get().Error("mlops: " + (target.targetSet.empty() ?
80+
("no default unnamed target set for '" + target.targetType + "'") :
81+
("target set '" + target.targetType + '@' + target.targetSet + "' not found")));
82+
return false;
83+
}
84+
}
85+
return true;
86+
}
87+
6488
string ProjMgrMlops::BuildActive(const string& targetType, const string& targetSet) const {
6589
return targetSet.empty() ? targetType : targetType + "@" + targetSet;
6690
}
@@ -110,41 +134,31 @@ bool ProjMgrMlops::CollectSettings(const CsolutionItem& csolution, MlopsType& ml
110134

111135
const auto& solutionMlops = csolution.mlops;
112136

113-
// hardware and simulator target types
114-
const string hardwareType = !solutionMlops.hardware.targetType.empty() ? solutionMlops.hardware.targetType :
115-
(!csolution.targetTypes.empty() ? csolution.targetTypes.front().first : RteUtils::EMPTY_STRING);
116-
const string simulatorType = !solutionMlops.simulator.targetType.empty() ? solutionMlops.simulator.targetType :
117-
(!csolution.targetTypes.empty() ? csolution.targetTypes.back().first : RteUtils::EMPTY_STRING);
118-
119-
// get hardware set
120-
TargetType hardwareTargetType;
121-
TargetSetItem hardwareTargetSet;
122-
if (!FindTargetType(csolution, hardwareType, hardwareTargetType) ||
123-
!GetTargetSetItemRef(hardwareTargetType, hardwareType, solutionMlops.hardware.targetSet, false, hardwareTargetSet)) {
124-
return false;
125-
}
126-
127-
// get simulator set
128-
TargetType simulatorTargetType;
129-
TargetSetItem simulatorTargetSet;
130-
if (!FindTargetType(csolution, simulatorType, simulatorTargetType) ||
131-
!GetTargetSetItemRef(simulatorTargetType, simulatorType, solutionMlops.simulator.targetSet, true, simulatorTargetSet)) {
137+
// resolve hardware and simulator targets and get references for their items
138+
string hardwareType, simulatorType;
139+
TargetSetItem hardwareTargetSet, simulatorTargetSet;
140+
if (!ResolveTargetSet(csolution, solutionMlops.hardware, false, hardwareType, hardwareTargetSet) ||
141+
!ResolveTargetSet(csolution, solutionMlops.simulator, true, simulatorType, simulatorTargetSet)) {
142+
// throw error if target is explicit specified but target set cannot be determined
132143
return false;
133144
}
134145

135146
// get all context items
136147
map<string, ContextItem>* contexts = nullptr;
137148
m_worker->GetContexts(contexts);
149+
if (contexts->empty()) {
150+
return false;
151+
}
138152

139153
// find hardware and simulator contexts
140154
vector<ContextItem> hardwareContexts, simulatorContexts;
141155
StrSet pnames;
142156
vector<tuple<const TargetSetItem&, const string&, vector<ContextItem>&>> refs = {
143157
{hardwareTargetSet, hardwareType, hardwareContexts}, {simulatorTargetSet, simulatorType, simulatorContexts}};
144158
for (auto& [targetSet, targetType, ref] : refs) {
145-
for (const auto& image : targetSet.images) {
146-
if (!image.context.empty()) {
147-
const string contextName = image.context + "+" + targetType;
159+
for (const auto& entry : targetSet.images) {
160+
if (!entry.context.empty()) {
161+
const string contextName = entry.context + "+" + targetType;
148162
if (contexts->find(contextName) != contexts->end()) {
149163
// process context precedences if needed
150164
auto& context = contexts->at(contextName);
@@ -164,27 +178,35 @@ bool ProjMgrMlops::CollectSettings(const CsolutionItem& csolution, MlopsType& ml
164178
}
165179

166180
// check if hardware and simulator contexts were found
167-
vector<tuple<const vector<ContextItem>&, const string&, const string&>> contextRefs = {
168-
{hardwareContexts, hardwareType, hardwareTargetSet.set},
169-
{simulatorContexts, simulatorType, simulatorTargetSet.set}
181+
vector<tuple<const vector<ContextItem>&, const MlopsTargetItem&>> contextRefs = {
182+
{hardwareContexts, solutionMlops.hardware},
183+
{simulatorContexts, solutionMlops.simulator}
170184
};
171-
for (const auto& [ref, targetType, targetSet] : contextRefs) {
172-
if (ref.empty()) {
173-
ProjMgrLogger::Get().Error("mlops: target-type '" + targetType + "' target-set '" +
174-
(targetSet.empty() ? "<default>" : targetSet) + "' project-contexts not found");
185+
for (const auto& [ref, t] : contextRefs) {
186+
if (!t.targetType.empty() && ref.empty()) {
187+
// print error if context for specified target type was not found
188+
ProjMgrLogger::Get().Error("mlops: no project-context specified for target '" +
189+
t.targetType + (t.targetSet.empty() ? "" : '@' + t.targetSet) + "'");
175190
return false;
176191
}
177192
}
178193

179-
auto& hardwareContext = hardwareContexts.front();
180-
auto& simulatorContext = simulatorContexts.front();
194+
// get hardware and simulator context references
195+
bool hardwareFound = !hardwareContexts.empty();
196+
bool simulatorFound = !simulatorContexts.empty();
197+
ContextItem emptyContext;
198+
ContextItem& hardwareContext = hardwareFound ? hardwareContexts.front() : emptyContext;
199+
ContextItem& simulatorContext = simulatorFound ? simulatorContexts.front() : emptyContext;
200+
201+
// if hardware is not determined use first default context for processor type and access sequences
202+
ContextItem& context = hardwareFound ? hardwareContext : contexts->begin()->second;
181203

182204
// mlops description
183205
mlops.description = solutionMlops.description;
184206

185207
// get hardware processor type ("Dcore")
186-
if (hardwareContext.targetAttributes.find("Dcore") != hardwareContext.targetAttributes.end()) {
187-
mlops.processor.type = hardwareContext.targetAttributes.at("Dcore");
208+
if (context.targetAttributes.find("Dcore") != context.targetAttributes.end()) {
209+
mlops.processor.type = context.targetAttributes.at("Dcore");
188210
}
189211

190212
// npu type and macs
@@ -244,40 +266,47 @@ bool ProjMgrMlops::CollectSettings(const CsolutionItem& csolution, MlopsType& ml
244266
} else {
245267
// explicit vela ini
246268
mlops.vela.ini = solutionMlops.vela.ini;
247-
if (!m_worker->ProcessSequenceRelative(hardwareContext, mlops.vela.ini, csolution.directory, false)) {
269+
if (!m_worker->ProcessSequenceRelative(context, mlops.vela.ini, csolution.directory, false)) {
248270
return false;
249271
}
250272
if (RteFsUtils::IsRelative(mlops.vela.ini)) {
251-
RteFsUtils::NormalizePath(mlops.vela.ini, hardwareContext.directories.cprj);
273+
RteFsUtils::NormalizePath(mlops.vela.ini, context.directories.cprj);
252274
}
253275
}
254-
276+
255277
// model name and clayer
256278
if (!solutionMlops.model.clayer.empty()) {
257279
mlops.model.name = solutionMlops.model.name.empty() ? "Algorithm" : solutionMlops.model.name;
258280
mlops.model.clayer = solutionMlops.model.clayer;
259-
if (!m_worker->ProcessSequenceRelative(hardwareContext, mlops.model.clayer, csolution.directory, false)) {
281+
if (!m_worker->ProcessSequenceRelative(context, mlops.model.clayer, csolution.directory, false)) {
260282
return false;
261283
}
262284
if (RteFsUtils::IsRelative(mlops.model.clayer)) {
263-
RteFsUtils::NormalizePath(mlops.model.clayer, hardwareContext.directories.cprj);
285+
RteFsUtils::NormalizePath(mlops.model.clayer, context.directories.cprj);
264286
}
265287
}
266288

267-
// set hardware and simulator run types
268-
const string outBaseDir = hardwareContext.directories.cprj + "/" + hardwareContext.directories.outBaseDir;
269-
SetMlopsRunType(mlops.hardware, hardwareType, hardwareTargetSet.set, hardwareContexts, outBaseDir, csolution.name);
270-
SetMlopsRunType(mlops.simulator, simulatorType, simulatorTargetSet.set, simulatorContexts, outBaseDir, csolution.name);
289+
if (hardwareFound) {
290+
// set hardware run types
291+
const string outBaseDir = hardwareContext.directories.cprj + "/" + hardwareContext.directories.outBaseDir;
292+
SetMlopsRunType(mlops.hardware, hardwareType, hardwareTargetSet.set, hardwareContexts, outBaseDir, csolution.name);
293+
}
271294

272-
// get debugger model and config-file
273-
mlops.simulator.model = GetCustomScalar(simulatorTargetSet.debugger.custom, "model");
274-
mlops.simulator.configFile = GetCustomScalar(simulatorTargetSet.debugger.custom, "config-file");
275-
if (!mlops.simulator.configFile.empty()) {
276-
if (!m_worker->ProcessSequenceRelative(simulatorContext, mlops.simulator.configFile, csolution.directory, false)) {
277-
return false;
278-
}
279-
if (RteFsUtils::IsRelative(mlops.simulator.configFile)) {
280-
RteFsUtils::NormalizePath(mlops.simulator.configFile, simulatorContext.directories.cprj);
295+
if (simulatorFound) {
296+
// set simulator run types
297+
const string outBaseDir = simulatorContext.directories.cprj + "/" + simulatorContext.directories.outBaseDir;
298+
SetMlopsRunType(mlops.simulator, simulatorType, simulatorTargetSet.set, simulatorContexts, outBaseDir, csolution.name);
299+
300+
// get debugger model and config-file
301+
mlops.simulator.model = GetCustomScalar(simulatorTargetSet.debugger.custom, "model");
302+
mlops.simulator.configFile = GetCustomScalar(simulatorTargetSet.debugger.custom, "config-file");
303+
if (!mlops.simulator.configFile.empty()) {
304+
if (!m_worker->ProcessSequenceRelative(simulatorContext, mlops.simulator.configFile, csolution.directory, false)) {
305+
return false;
306+
}
307+
if (RteFsUtils::IsRelative(mlops.simulator.configFile)) {
308+
RteFsUtils::NormalizePath(mlops.simulator.configFile, simulatorContext.directories.cprj);
309+
}
281310
}
282311
}
283312

tools/projmgr/test/data/MLOps/failure2.csolution.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ solution:
55

66
mlops:
77
simulator:
8-
target: OtherSimulator
8+
target: Simulator@OtherSet
99

1010
target-types:
1111
- type: Hardware

tools/projmgr/test/data/MLOps/failure3.csolution.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,26 @@ solution:
44
compiler: AC6
55

66
mlops:
7+
simulator:
8+
target: Simulator@FVP-Test
79

810
target-types:
911
- type: Hardware
1012
device: RteTest_ARMCM0_Dual
1113
target-set:
1214
- set:
15+
images:
16+
- project-context: core0
17+
- project-context: core1
18+
1319
- type: Simulator
1420
device: RteTest_ARMCM0_Dual
1521
target-set:
1622
- set: FVP-Test
23+
debugger:
24+
name: Arm-FVP
25+
images:
26+
- project-context: wrong_context
1727

1828
projects:
1929
- project: core0/core0.cproject.yml

tools/projmgr/test/data/MLOps/minimal.csolution.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ solution:
2121

2222
- type: Simulator
2323
device: RteTest_ARMCM0_Dual
24-
define:
25-
- SIMULATOR
2624
variables:
2725
- AI-Layer: $SolutionDir()$/ai_layer/ai_layer.clayer.yml
2826
target-set:
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json
2+
3+
solution:
4+
compiler: AC6
5+
6+
mlops:
7+
description: hardware target not present
8+
model:
9+
clayer: $AI-Layer$
10+
11+
target-types:
12+
- type: Simulator
13+
device: RteTest_ARMCM0_Dual
14+
variables:
15+
- AI-Layer: $SolutionDir()$/ai_layer/ai_layer.clayer.yml
16+
target-set:
17+
- set: FVP-Test
18+
debugger:
19+
name: Arm-FVP
20+
model: FVP_Corstone_SSE-320
21+
config-file: fvp/fvp_config.txt
22+
images:
23+
- project-context: core0
24+
- project-context: core1
25+
26+
projects:
27+
- project: core0/core0.cproject.yml
28+
- project: core1/core1.cproject.yml

tools/projmgr/test/data/MLOps/failure4.csolution.yml renamed to tools/projmgr/test/data/MLOps/no_simulator.csolution.yml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,21 @@ solution:
44
compiler: AC6
55

66
mlops:
7+
description: simulator target not present
8+
model:
9+
clayer: $AI-Layer$
710

811
target-types:
912
- type: Hardware
1013
device: RteTest_ARMCM0_Dual
14+
variables:
15+
- AI-Layer: $SolutionDir()$/ai_layer/ai_layer.clayer.yml
1116
target-set:
1217
- set:
1318
images:
1419
- project-context: core0
1520
- project-context: core1
1621

17-
- type: Simulator
18-
device: RteTest_ARMCM0_Dual
19-
target-set:
20-
- set: FVP-Test
21-
debugger:
22-
name: Arm-FVP
23-
images:
24-
- project-context: wrong_context
25-
2622
projects:
2723
- project: core0/core0.cproject.yml
2824
- project: core1/core1.cproject.yml

0 commit comments

Comments
 (0)