1function myLN = parseXML(filename, verbose)
2% MYLN = PARSEXML(FILENAME, VERBOSE)
4% Copyright (c) 2012-2026, Imperial College London
8import javax.xml.parsers.DocumentBuilderFactory;
9import javax.xml.parsers.DocumentBuilder;
10import org.w3c.dom.Document;
11import org.w3c.dom.NodeList;
12import org.w3c.dom.Node;
13import org.w3c.dom.Element;
16import LayeredNetwork.*;
19myLN = LayeredNetwork(strrep(filename,
'_',
'\_'));
21if nargin<2%~exist(
'verbose',
'var')
25% init Java XML parser and load file
26dbFactory = DocumentBuilderFactory.newInstance();
27dBuilder = dbFactory.newDocumentBuilder();
29fid=fopen(filename,'r');
31 line_error(mfilename,'File cannot be found. Verify the current directory and the specified filename.');
36if isempty(fileparts(filename))
37 doc = dBuilder.parse(which(filename));
39 doc = dBuilder.parse(filename);
41doc.getDocumentElement().normalize();
43 line_printf(['Parsing LQN file: ',filename]);
44 line_printf(['Root element :',
char(doc.getDocumentElement().getNodeName())]);
47hosts = cell(0); %list of hosts - Proc
48tasks = cell(0); %list of tasks - Task, ProcID
49entries = cell(0); %list of entries - Entry, TaskID, ProcID
50activities = cell(0); %list of activities - Act, TaskID, ProcID
60procList = doc.getElementsByTagName('processor');
61for i = 0:procList.getLength()-1
63 procElement = procList.item(i);
64 name =
char(procElement.getAttribute('name'));
65 scheduling =
char(procElement.getAttribute('scheduling'));
66 multiplicity = str2double(
char(procElement.getAttribute('multiplicity')));
67 replication = str2double(
char(procElement.getAttribute('replication')));
72 if strcmp(scheduling, 'inf')
73 if isfinite(multiplicity)
74 line_warning(mfilename,'A finite multiplicity
is specified for a host processor with INF scheduling. Remove it or set it to "inf".\n');
77 elseif isnan(multiplicity)
80 quantum = str2double(
char(procElement.getAttribute('quantum')));
84 speedFactor = str2double(
char(procElement.getAttribute('speed-factor')));
88 newProc = Processor(myLN, name, multiplicity, SchedStrategy.fromText(scheduling), quantum, speedFactor);
89 newProc.setReplication(replication);
90 procObj{end+1,1} = newProc;
92 taskList = procElement.getElementsByTagName(
'task');
93 for j = 0:taskList.getLength()-1
95 taskElement = taskList.item(j);
96 name = char(taskElement.getAttribute(
'name'));
97 scheduling = char(taskElement.getAttribute(
'scheduling'));
98 replication = str2double(
char(taskElement.getAttribute(
'replication')));
103 multiplicity = str2double(
char(taskElement.getAttribute(
'multiplicity')));
104 if strcmp(scheduling,
'inf')
105 if isfinite(multiplicity)
106 line_warning(mfilename,'A finite multiplicity
is specified for a task with inf scheduling. Remove it or set it to inf.\n');
109 elseif isnan(multiplicity)
112 thinkTimeMean = str2double(
char(taskElement.getAttribute('think-time')));
113 if isnan(thinkTimeMean)
116 if thinkTimeMean <= 0.0
117 thinkTime = Immediate.getInstance();
119 thinkTime = Exp.fitMean(thinkTimeMean);
121 newTask = Task(myLN, name, multiplicity, SchedStrategy.fromText(scheduling), thinkTime);
122 newTask.setReplication(replication);
124 % Parse priority attribute if present
125 priorityStr =
char(taskElement.getAttribute('priority'));
126 if ~isempty(priorityStr)
127 priority = str2double(priorityStr);
129 newTask.setPriority(priority);
133 % Parse fan-in element if present (used for replication load distribution)
134 fanInList = taskElement.getElementsByTagName('fan-in');
135 if fanInList.getLength() > 0
136 fanInElement = fanInList.item(0);
137 source =
char(fanInElement.getAttribute('source'));
138 valueStr =
char(fanInElement.getAttribute('value'));
139 if ~isempty(source) && ~isempty(valueStr)
140 value = str2double(valueStr);
142 newTask.setFanIn(source, value);
147 taskObj{end+1,1} = newTask;
149 entryList = taskElement.getElementsByTagName(
'entry');
150 for k = 0:entryList.getLength()-1
152 entryElement = entryList.item(k);
153 name = char(entryElement.getAttribute(
'name'));
154 newEntry = Entry(myLN, name);
155 openArrivalRate = str2double(
char(entryElement.getAttribute(
'open-arrival-rate')));
156 if ~isnan(openArrivalRate)
157 newEntry.openArrivalRate = openArrivalRate;
160 % Parse entry type attribute
161 eType = char(entryElement.getAttribute(
'type'));
163 newEntry.setType(eType);
166 entryObj{end+1,1} = newEntry;
168 % Parse forwarding calls
169 forwardingList = entryElement.getElementsByTagName(
'forwarding');
170 for fw = 0:forwardingList.getLength()-1
171 fwdElement = forwardingList.item(fw);
172 destName = char(fwdElement.getAttribute(
'dest'));
173 probStr = char(fwdElement.getAttribute(
'prob'));
177 prob = str2double(probStr);
179 newEntry.forward(destName, prob);
182 %entry-phase-activities
183 entryPhaseActsList = entryElement.getElementsByTagName(
'entry-phase-activities');
184 if entryPhaseActsList.getLength > 0
185 entryPhaseActsElement = entryPhaseActsList.item(0);
186 actList = entryPhaseActsElement.getElementsByTagName(
'activity');
187 name = cell(actList.getLength(),1);
188 for l = 0:actList.getLength()-1
190 actElement = actList.item(l);
191 phase = str2double(
char(actElement.getAttribute(
'phase')));
192 name{phase} = char(actElement.getAttribute(
'name'));
193 hostDemandMean = str2double(
char(actElement.getAttribute(
'host-demand-mean')));
194 hostDemandSCV = str2double(
char(actElement.getAttribute(
'host-demand-cvsq')));
195 if isnan(hostDemandSCV)
198 if hostDemandMean <= 0.0
199 hostDemand = Immediate.getInstance();
201 if hostDemandSCV <= 0.0
202 hostDemand = Det(hostDemandMean);
203 elseif hostDemandSCV == 1.0
204 hostDemand = Exp.fitMean(hostDemandMean);
206 hostDemand = APH.fitMeanAndSCV(hostDemandMean, hostDemandSCV);
210 boundToEntry = newEntry.name;
214 callOrder = char(actElement.getAttribute(
'call-order'));
215 newAct = Activity(myLN, name{phase}, hostDemand, boundToEntry, callOrder);
216 newAct.phase = phase; % Store the phase number
218 % Parse activity think-time
219 actThinkTimeMean = str2double(
char(actElement.getAttribute(
'think-time')));
220 if ~isnan(actThinkTimeMean) && actThinkTimeMean > 0.0
221 newAct.setThinkTime(actThinkTimeMean);
224 actObj{end+1,1} = newAct;
227 synchCalls = actElement.getElementsByTagName(
'synch-call');
228 for m = 0:synchCalls.getLength()-1
229 callElement = synchCalls.item(m);
230 dest = char(callElement.getAttribute(
'dest'));
231 mean = str2double(
char(callElement.getAttribute(
'calls-mean')));
232 newAct = newAct.synchCall(dest,mean);
236 asynchCalls = actElement.getElementsByTagName(
'asynch-call');
237 for m = 0:asynchCalls.getLength()-1
238 callElement = asynchCalls.item(m);
239 dest = char(callElement.getAttribute(
'dest'));
240 mean = str2double(
char(callElement.getAttribute(
'calls-mean')));
241 newAct = newAct.asynchCall(dest,mean);
244 activities{end+1,1} = newAct.name;
245 activities{end,2} = taskID;
246 activities{end,3} = procID;
247 newTask = newTask.addActivity(newAct);
248 newAct.parent = newTask;
253 for l = 1:length(name)-1
254 newPrec = ActivityPrecedence(name(l), name(l+1));
255 newTask = newTask.addPrecedence(newPrec);
258 %reply-entry: For entry-phase-activities, phase-1 activities reply implicitly
259 % Find the last phase-1 activity and set it as the reply activity
260 if ~isempty(name) && ~isempty(name{1})
261 % The last phase-1 activity (name{1}) should reply to the entry
262 newEntry.replyActivity{end+1} = name{1};
266 entries{end+1,1} = newEntry.name;
267 entries{end,2} = taskID;
268 entries{end,3} = procID;
269 newTask = newTask.addEntry(newEntry);
270 newEntry.parent = newTask;
275 taskActsList = taskElement.getElementsByTagName(
'task-activities');
276 if taskActsList.getLength > 0
277 taskActsElement = taskActsList.item(0);
278 actList = taskActsElement.getElementsByTagName(
'activity');
279 for l = 0:actList.getLength()-1
281 actElement = actList.item(l);
282 if strcmp(
char(actElement.getParentNode().getNodeName()),
'task-activities')
283 name =
char(actElement.getAttribute('name'));
284 hostDemandMean = str2double(
char(actElement.getAttribute('host-demand-mean')));
285 hostDemandSCV = str2double(
char(actElement.getAttribute('host-demand-cvsq')));
286 if isnan(hostDemandSCV)
289 if hostDemandMean <= 0.0
290 hostDemand = Immediate.getInstance();
292 if hostDemandSCV <= 0.0
293 hostDemand = Det(hostDemandMean);
294 elseif hostDemandSCV < 1.0
295 hostDemand = APH.fitMeanAndSCV(hostDemandMean, hostDemandSCV);
296 elseif hostDemandSCV == 1.0
297 hostDemand = Exp.fitMeanAndSCV(hostDemandMean, hostDemandSCV);
299 hostDemand = HyperExp.fitMeanAndSCV(hostDemandMean, hostDemandSCV);
302 boundToEntry =
char(actElement.getAttribute('bound-to-entry'));
303 callOrder =
char(actElement.getAttribute('call-order'));
304 newAct = Activity(myLN, name, hostDemand, boundToEntry, callOrder);
306 % Parse activity think-time
307 actThinkTimeMean = str2double(
char(actElement.getAttribute('think-time')));
308 if ~isnan(actThinkTimeMean) && actThinkTimeMean > 0.0
309 newAct.setThinkTime(actThinkTimeMean);
312 actObj{end+1,1} = newAct;
315 synchCalls = actElement.getElementsByTagName(
'synch-call');
316 for m = 0:synchCalls.getLength()-1
317 callElement = synchCalls.item(m);
318 dest = char(callElement.getAttribute(
'dest'));
319 mean = str2double(
char(callElement.getAttribute(
'calls-mean')));
320 newAct = newAct.synchCall(dest,mean);
324 asynchCalls = actElement.getElementsByTagName(
'asynch-call');
325 for m = 0:asynchCalls.getLength()-1
326 callElement = asynchCalls.item(m);
327 dest = char(callElement.getAttribute(
'dest'));
328 mean = str2double(
char(callElement.getAttribute(
'calls-mean')));
329 newAct = newAct.asynchCall(dest,mean);
332 activities{end+1,1} = newAct.name;
333 activities{end,2} = taskID;
334 activities{end,3} = procID;
335 newTask = newTask.addActivity(newAct);
336 newAct.parent = newTask;
342 precList = taskActsElement.getElementsByTagName(
'precedence');
343 for l = 0:precList.getLength()-1
344 precElement = precList.item(l);
347 preTypes = {ActivityPrecedenceType.PRE_SEQ,ActivityPrecedenceType.PRE_AND,ActivityPrecedenceType.PRE_OR};
348 for m = 1:length(preTypes)
349 preType = preTypes{m};
350 preList = precElement.getElementsByTagName(ActivityPrecedenceType.toText(preType));
351 if preList.getLength() > 0
355 preElement = preList.item(0);
357 preActList = preElement.getElementsByTagName(
'activity');
359 % assumes that preType
is a numeric precedence ID
360 %
if strcmp(preType,ActivityPrecedenceType.toText(ActivityPrecedenceType.PRE_OR))
361 if preType == ActivityPrecedenceType.PRE_OR
362 preActs = cell(preActList.getLength(),1);
363 preParams = zeros(postActList.getLength(),1);
364 for m = 0:preActList.getLength()-1
365 preActElement = preActList.item(m);
366 preActs{m+1} = char(preActElement.getAttribute(
'name'));
367 preParams(m+1) = str2double(
char(preActElement.getAttribute(
'prob')));
369 % elseif strcmp(preType,ActivityPrecedenceType.toText(ActivityPrecedenceType.PRE_AND))
370 elseif preType == ActivityPrecedenceType.PRE_AND
371 preActs = cell(preActList.getLength(),1);
372 for m = 0:preActList.getLength()-1
373 preActElement = preActList.item(m);
374 preActs{m+1} = char(preActElement.getAttribute(
'name'));
376 preParams = str2double(
char(preElement.getAttribute(
'quorum')));
379 preActElement = preActList.item(0);
380 preActs{1} = char(preActElement.getAttribute(
'name'));
387 postTypes = {ActivityPrecedenceType.POST_SEQ, ActivityPrecedenceType.POST_AND, ActivityPrecedenceType.POST_OR, ActivityPrecedenceType.POST_LOOP, ActivityPrecedenceType.POST_CACHE};
388 for m = 1:length(postTypes)
389 postType = postTypes{m};
390 postList = precElement.getElementsByTagName(ActivityPrecedenceType.toText(postType));
391 if postList.getLength() > 0
396 postElement = postList.item(0);
397 postActList = postElement.getElementsByTagName(
'activity');
399 % assumes that postType
is a numeric precedence ID
400 %
if strcmp(postType,ActivityPrecedenceType.toText(ActivityPrecedenceType.POST_OR))
401 if postType == ActivityPrecedenceType.POST_OR
402 postActs = cell(postActList.getLength(),1);
403 postParams = zeros(postActList.getLength(),1);
404 for m = 0:postActList.getLength()-1
405 postActElement = postActList.item(m);
406 postActs{m+1} = char(postActElement.getAttribute(
'name'));
407 postParams(m+1) = str2double(
char(postActElement.getAttribute(
'prob')));
409 %elseif strcmp(postType,ActivityPrecedenceType.toText(ActivityPrecedenceType.POST_LOOP))
410 elseif postType == ActivityPrecedenceType.POST_LOOP
411 postActs = cell(postActList.getLength()+1,1);
412 postParams = zeros(postActList.getLength(),1);
413 for m = 0:postActList.getLength()-1
414 postActElement = postActList.item(m);
415 postActs{m+1} = char(postActElement.getAttribute(
'name'));
416 postParams(m+1) = str2double(
char(postActElement.getAttribute(
'count')));
419 postActs{end} = char(postElement.getAttribute(
'end'));
421 postActs = cell(postActList.getLength(),1);
423 for m = 0:postActList.getLength()-1
424 postActElement = postActList.item(m);
425 postActs{m+1} = char(postActElement.getAttribute(
'name'));
428 newPrec = ActivityPrecedence(preActs, postActs, preType, postType, preParams, postParams);
429 newTask = newTask.addPrecedence(newPrec);
433 replyList = taskActsElement.getElementsByTagName(
'reply-entry');
434 for l = 0:replyList.getLength()-1
435 replyElement = replyList.item(l);
436 replyName = char(replyElement.getAttribute(
'name'));
437 replyIdx = findstring(entries(:,1), replyName);
438 replyActList = replyElement.getElementsByTagName(
'reply-activity');
439 for m = 0:replyActList.getLength()-1
440 replyActElement = replyActList.item(m);
441 replyActName = char(replyActElement.getAttribute(
'name'));
442 entryObj{replyIdx}.replyActivity{end+1} = replyActName;
447 tasks{end+1,1} = newTask.name;
448 tasks{end,2} = procID;
449 newProc = newProc.addTask(newTask);
453 hosts{end+1,1} = newProc.name;