Mercurial > hg > ltpda
comparison m-toolbox/classes/@LTPDAworkbench/cmds2pipeline.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
1 % CMDS2PIPELINE builds new pipelines in the given workbench from the | |
2 % set of LTPDA commands. | |
3 % | |
4 % CALL: cmds2pipeline(wb, name, cmds) | |
5 % cmds2pipeline(wb, name, cmds, blockpositions) | |
6 % | |
7 % M Hewitson 12-11-10 | |
8 % | |
9 % $Id: cmds2pipeline.m,v 1.2 2011/04/08 08:56:32 hewitson Exp $ | |
10 % | |
11 function cmds2pipeline(wb, docname, cmds, varargin) | |
12 | |
13 if numel(varargin) > 0 | |
14 blockPositions = varargin{1}; | |
15 else | |
16 blockPositions = {}; | |
17 end | |
18 | |
19 % create new diagram | |
20 awtinvoke(wb.mp, 'createNewBlockDiagram', docname); | |
21 % logical array for checking that we only place | |
22 % each block once | |
23 blockplaced = zeros(size(cmds)); | |
24 | |
25 % Go through each command and place its block | |
26 cn = 1; | |
27 dX = 100; | |
28 dY = 150; | |
29 sX = 100; | |
30 X = sX; % starting X coord | |
31 Y = 50; % starting Y coord | |
32 % loop until all blocks are placed | |
33 blockNames = {}; | |
34 while ~all(blockplaced) && cn <=numel(cmds) | |
35 if ~blockplaced(cn) | |
36 % parse this command | |
37 srcblock = LTPDAworkbench.parseCmd(cmds{cn}); | |
38 %--------- build a block | |
39 % to do this we need an minfo object; we have the | |
40 % the method name but we need the class. Either this | |
41 % is a constructor or it must have an input object | |
42 ecmd = sprintf('%s.getInfo(''%s'');', srcblock.class, srcblock.method); | |
43 ii = eval(ecmd); | |
44 % override auto-generated positions if the user supplies them | |
45 if ~isempty(blockPositions) | |
46 pos = blockPositions{cn}; | |
47 X = pos(1); | |
48 Y = pos(2); | |
49 end | |
50 name = wb.addBlock(srcblock.outname, ii, X,Y); | |
51 blockNames = [blockNames {name}]; | |
52 blockplaced(cn) = 1; | |
53 % look for commands which take this output as an input | |
54 [blockplaced,blockNames] = placeBlock(wb, blockplaced, ... | |
55 blockPositions, srcblock.outname, cmds, X, dX, Y, cn, blockNames); | |
56 % reset X | |
57 X = sX+floor(utils.math.rand(10,20)); | |
58 % increment in Y | |
59 Y = Y + dY; | |
60 end | |
61 % check next block | |
62 cn = cn + 1; | |
63 end | |
64 | |
65 % Build a connection list | |
66 connections = struct('src', {}, 'srcport', {}, 'dst',{}, 'dstport', {}); | |
67 cc = 1; | |
68 for cn =1:numel(cmds) | |
69 conn = cmd2conn(cmds{cn}); | |
70 % deal with block-to-block connections | |
71 if numel(conn.srcports)==numel(conn.dstports) | |
72 for kk=1:numel(conn.srcblocks) | |
73 if numel(conn.srcblocks) == 1 | |
74 % one-to-many | |
75 srcb = conn.srcblocks{1}; | |
76 else | |
77 % one-to-one | |
78 srcb = conn.srcblocks{kk}; | |
79 end | |
80 if numel(conn.dstblocks) == 1 | |
81 % many-to-one | |
82 dstb = conn.dstblocks{1}; | |
83 else | |
84 % one-to-one | |
85 dstb = conn.dstblocks{kk}; | |
86 end | |
87 if ~isempty(srcb) && ~isempty(dstb) | |
88 % make connection | |
89 if ~isempty(dstb) | |
90 connections(cc) = struct('src', srcb, ... | |
91 'srcport', conn.srcports(kk), ... | |
92 'dst', dstb, ... | |
93 'dstport', conn.dstports(kk)); | |
94 connections(end) | |
95 wb.connectBlocks(connections(cc).src, connections(cc).srcport+1, ... | |
96 connections(cc).dst, connections(cc).dstport+1); | |
97 cc = cc + 1; | |
98 end | |
99 end | |
100 end % End loop over src blocks | |
101 end | |
102 end % End first loop over commands | |
103 | |
104 % also deal with connections to the plist | |
105 for kk=1:numel(cmds) | |
106 cconn = cmd2conn(cmds{kk}); | |
107 conn = connFromPlist(cconn, blockNames); | |
108 if ~isempty(conn) | |
109 for ll=1:numel(conn) | |
110 % we need to know what destination port to use | |
111 % - look for max in connections for this dst block | |
112 b = wb.getBlockByName(conn(ll).dst); | |
113 p = b.getNextFreeInput(); | |
114 connections(cc) = struct('src', conn(ll).src, ... | |
115 'srcport', conn(ll).srcport, ... | |
116 'dst', conn(ll).dst, ... | |
117 'dstport', p); | |
118 wb.connectBlocks(conn(ll).src, conn(ll).srcport+1, conn(ll).dst, p+1) | |
119 cc = cc + 1; | |
120 end | |
121 end | |
122 end | |
123 | |
124 % upload plists | |
125 for cn =1:numel(cmds) | |
126 block = LTPDAworkbench.parseCmd(cmds{cn}); | |
127 dstblock = block.outname; | |
128 % get src block name(s) and ports from each plist | |
129 for pp=1:numel(block.plists) | |
130 pl = block.plists{pp}; | |
131 mtchs = regexp(pl, '(\w*)_PORT(\d*)', 'tokens'); | |
132 % for each match, we look for a corresponding connection | |
133 % so that we can determine the destination port | |
134 if ~isempty(mtchs) | |
135 for kk=1:numel(mtchs) | |
136 srcblock = mtchs{kk}{1}; | |
137 srcport = str2double(mtchs{kk}{2}); | |
138 % look for srcblock/srcport/dstblock in connection list | |
139 % and get the dstport | |
140 dstport = -1; | |
141 for cc=1:numel(connections) | |
142 % if this matches... | |
143 if strcmp(connections(cc).src, srcblock) && ... | |
144 strcmp(connections(cc).dst, dstblock) && ... | |
145 connections(cc).srcport == srcport | |
146 % ... then we set the dstport | |
147 dstport = connections(cc).dstport; | |
148 end | |
149 end | |
150 % now we can fix up the plist | |
151 if dstport >= 0 | |
152 pl = regexprep(pl, [srcblock '_PORT\d*'], ['''PORT_' num2str(dstport) '''']); | |
153 end | |
154 end | |
155 else | |
156 % Try also for any block name in the plist | |
157 for kk=1:numel(blockNames) | |
158 srcblock = blockNames{kk}; | |
159 % look for this srcblock in the plist but we need a clever | |
160 % regular expression to check this is an argument of the plist and | |
161 % not part of a key, for example. | |
162 tks = regexp(pl, ['[\s\[,]+(' srcblock ')[\s,\]]+'], 'tokens'); | |
163 dstport = -1; | |
164 for ll=1:numel(tks) | |
165 % To get the destination port, we need to find this | |
166 % connection in the connections list | |
167 for cc=1:numel(connections) | |
168 cnc = connections(cc); | |
169 if strcmp(cnc.src, srcblock) && ... | |
170 strcmp(cnc.dst, dstblock) && ... | |
171 cnc.srcport == 0 | |
172 dstport = cnc.dstport; | |
173 end | |
174 end | |
175 end | |
176 if dstport >= 0 | |
177 pl = regexprep(pl, srcblock, ['''PORT_' num2str(dstport) '''']); | |
178 end | |
179 end | |
180 end | |
181 % now we can upload the plist | |
182 wb.uploadPlist(dstblock, eval(pl)); | |
183 end | |
184 end | |
185 | |
186 | |
187 end | |
188 | |
189 %-------------------------------------------------------------------------- | |
190 % Create a connection structure from a plist. | |
191 % | |
192 % This deals with those plists that have BLOCK_PORT# type entries. | |
193 % | |
194 function conn = connFromPlist(iconn, blocks) | |
195 | |
196 conn = struct('src', {}, 'srcport', {}, 'dst',{}, 'dstport', {}); | |
197 cc = 1; | |
198 | |
199 for jj=1:numel(iconn.plist) | |
200 pl = iconn.plist{jj}; | |
201 dsts = regexp(pl, '\w*_PORT\d*','match'); | |
202 if ~isempty(dsts) | |
203 for kk=1:numel(dsts) | |
204 % parse dst string | |
205 tks = regexp(dsts{kk}, '(\w*)_PORT(\d*)', 'tokens'); | |
206 for ll=1:numel(tks) | |
207 % make a connection | |
208 src = tks{ll}{1}; | |
209 srcp = tks{ll}{2}; | |
210 conn(cc).src = src; | |
211 conn(cc).srcport = str2double(srcp); | |
212 conn(cc).dst = iconn.dstblocks{1}; | |
213 conn(cc).dstport = -1; % next free port | |
214 cc = cc + 1; | |
215 end | |
216 end | |
217 else | |
218 % also look for any input variables which are block names but have | |
219 % no _PORT# suffix | |
220 for kk=1:numel(blocks) | |
221 srcblock = blocks{kk}; | |
222 % look for this srcblock in the plist but we need a clever | |
223 % regular expression to check this is an argument of the plist and | |
224 % not part of a key, for example. | |
225 tks = regexp(pl, ['[\s\[,]+(' srcblock ')[\s,\]]+'], 'tokens'); | |
226 for ll=1:numel(tks) | |
227 conn(cc).src = tks{ll}{1}; | |
228 conn(cc).srcport = 0; | |
229 conn(cc).dst = iconn.dstblocks{1}; | |
230 conn(cc).dstport = -1; % next free port | |
231 cc = cc + 1; | |
232 end | |
233 end | |
234 end | |
235 end | |
236 end | |
237 | |
238 %-------------------------------------------------------------------------- | |
239 % Convert a connection to a command. | |
240 % | |
241 function conn = cmd2conn(cmd) | |
242 | |
243 block = LTPDAworkbench.parse(cmd); | |
244 | |
245 % first get block name from end | |
246 [s,r] = strtok(block.comment, '|'); | |
247 if ~isempty(r) | |
248 blockname = {strrep(strtrim(r(2:end)), ' ', '_')}; | |
249 else | |
250 blockname = ''; | |
251 end | |
252 | |
253 [outname,outports] = fixBlockdiagramName(block.outvars{1}); | |
254 | |
255 if isempty(blockname) | |
256 blockname = block.outvars(1); | |
257 end | |
258 | |
259 innames = {}; | |
260 srcports = []; | |
261 for kk=1:numel(block.invars) | |
262 [s,p] = fixBlockdiagramName(block.invars{kk}); | |
263 if isempty(p) | |
264 p = 0; | |
265 end | |
266 innames = [innames s]; | |
267 srcports = [srcports p]; | |
268 end | |
269 | |
270 % trim all strings and build output struct | |
271 conn.srcblocks = innames; | |
272 conn.srcports = srcports; | |
273 conn.dstblocks = blockname; | |
274 conn.dstports = [1:numel(innames)]-1; | |
275 conn.plist = block.pls; | |
276 | |
277 end | |
278 | |
279 %-------------------------------------------------------------------------- | |
280 % Do some parsing of block diagram names to make sensible variable names. | |
281 % | |
282 function [name, ports] = fixBlockdiagramName(name) | |
283 | |
284 name = strtrim(name); | |
285 if name(1) == '[' && name(end) == ']' | |
286 name = name(2:end-1); | |
287 end | |
288 % match the last occurance of '_PORT' and check there is a | |
289 % number behind it | |
290 pstrs = regexp(name, '_PORT(\d*)', 'tokens'); | |
291 ports = []; | |
292 for kk=1:numel(pstrs) | |
293 ports(kk) = str2double(pstrs{kk}{1}); | |
294 end | |
295 | |
296 name = regexprep(name, '_PORT\d*', ''); | |
297 end | |
298 | |
299 %-------------------------------------------------------------------------- | |
300 % Place a block on the canvas | |
301 % | |
302 function [blockplaced,blockNames] = placeBlock(wb, blockplaced, blockPositions, ... | |
303 outname, cmds, X, dX, Y, cn, blockNames) | |
304 | |
305 % look for commands which take this output as an input | |
306 for kk=1:numel(cmds) | |
307 dstblock = LTPDAworkbench.parseCmd(cmds{kk}); | |
308 if any(strcmp(outname, dstblock.innames)) %|| ~isempty(idx) | |
309 if ~blockplaced(kk) | |
310 blockplaced(kk) = 1; | |
311 %--------- build a block | |
312 % to do this we need an minfo object; we have the | |
313 % the method name but we need the class. Either this | |
314 % is a constructor or it must have an input object | |
315 ecmd = sprintf('%s.getInfo(''%s'');', dstblock.class, dstblock.method); | |
316 ii = eval(ecmd); | |
317 X = X + dX; | |
318 Y = Y + 30; | |
319 if ~isempty(blockPositions) | |
320 pos = blockPositions{kk}; | |
321 X = pos(1); | |
322 Y = pos(2); | |
323 end | |
324 name = wb.addBlock(dstblock.outname, ii, X,Y); | |
325 blockNames = [blockNames {name}]; | |
326 % name = wb.addBlock(doutname, ii, X,Y+ (mod(cn+kk-1,2))*50); | |
327 % recursively call for this block | |
328 [blockplaced,blockNames] = placeBlock(wb, blockplaced, blockPositions, ... | |
329 dstblock.outname, cmds, X, dX, Y, cn, blockNames); | |
330 end | |
331 end | |
332 end | |
333 | |
334 end | |
335 | |
336 %-------------------------------------------------------------------------- | |
337 % Replace other block names with PORT_# | |
338 % | |
339 % #### OLD CODE ##### | |
340 % | |
341 function [pl, newconnections] = fixpl(pl,connections) | |
342 | |
343 % first we need to replace all BLOCK_PORT# with PORT_# | |
344 pl = regexprep(pl, '(\w*)_PORT(\d*)', '''PORT_$2'''); | |
345 | |
346 cn = 1; | |
347 % go through all connections | |
348 for kk=1:numel(connections) | |
349 conn = connections(kk); | |
350 % check if the plist has a token matching the src | |
351 rstr = ['[' conn.src ']']; | |
352 nstr = sprintf('''PORT_%d''', conn.dstport-1); | |
353 idx = strfind(pl, rstr); | |
354 pl = strrep(pl, rstr, nstr); | |
355 if ~isempty(idx) | |
356 newconnections(cn) = struct('src', conn.src, 'dst', conn.dst, ... | |
357 'srcport', conn.srcport, 'dstport', conn.dstport-1); | |
358 end | |
359 end | |
360 | |
361 end | |
362 | |
363 % END |