5610397fb2dcdd4f31d74fd4c8a15d1873f82129
[scilab.git] / scilab / modules / scicos / macros / scicos_scicos / scicos_flat.sci
1 //  Scicos
2 //
3 //  Copyright (C) INRIA - METALAU Project <scicos@inria.fr>
4 //                      - Ramine Nikoukhah <ramine.nikoukhah@inria.fr> - 2003
5 //                      - Serge Steer <serge.steer@inria.fr>           - 2003
6 //                      - Fady Nassif <fady.nassif@inria.fr>           - 2007
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 //
22 // See the file ../license.txt
23 //
24
25 function  [cor,corinv,links_table,cur_fictitious,sco_mat,ok, IN, OUT, EIN, EOUT]=scicos_flat(scs_m,ksup,MaxBlock)
26     //This function takes a hierarchical Scicos diagram and computes the
27     //"flat" equivalent, removing "non computational" blocs like splits.
28     //S. Steer, R. Nikoukhah 2003. Copyright INRIA
29
30     //NB::--------------------------------------------------------------
31     // Modifying this function to take care of the GOTO FROM SampleCLK and VirtualCLK0 blocks.
32     // A negatif number in cor and in links_table is refer to a GOTO,FROM
33     // GotoTagVisibility, SampleCLK, VirtualCLK0. in other words the blocks that are virtual.
34     // These blocks are removed in the compilation part.
35     // Modification of shiftcors. It will not shift the negatives numbers.
36     // A sco_mat is a string matrix composed by the :
37     // For the blocks GOTO, FROM, VirtualCLK0
38     //  - the first column : the negatif of the number of the virtual block in the cor.
39     //  - the second column: 1 if it is a GOTO; -1 if it is a FROM.
40     //                           The VirtualCLK0 is considered as a GOTO.
41     //  - the third column : the tag value. 'scicostimeclk0' is used in the case of the VirtualCLK0
42     //  - the forth column : the tag visibility
43     //                           For the GOTO: + 2: scoped
44     //                                         + 3: global
45     //                           For the FROM: + 1
46     //                           For the VirtualCLK0: 2
47     //  - the fifth column : 1=regular 2=event 3=modelica 10=VirtualCLK0
48     // For the SampleCLK:
49     //  - the first column : the negatif of the number of the virtual block in the cor.
50     //  - the second column: the value 1.
51     //  - the third column : The frequency value.
52     //  - the forth column : The offset value.
53     //  - the fifth column : the value 4.
54     // Another two string matrices are used for the GOTO/FROM blocks. The loc_mat it is used when the GOTO
55     // block is local. The from_mat to match the local from with the local goto.
56     // A tag_exprs matrices is used for the GotoTagVisibility and the VirtualCLK0:
57     // it is composed by:
58     //       - the first column: The tag value. 'scicostimeclk0' in the VirtualCLK0 case.
59     //       - the second column: 1=regular 2=event 3=modelica 10=VirtualCLK0
60     // The local and scoped cases are studied in this function.
61     // The global case is studied in the function global_case in c_pass1.
62     // A Modification of update_cor in c_pass1. For the negatives numbers
63     // the cor will be set to 0. (In this case the blocks are considered as IN_f ...)
64     // Fady NASSIF 2007. INRIA.
65     //-------------------------------------------------------------------
66
67     if argn(2)<=1 then ksup=0;end //used for recursion
68     if ksup==0 then   // main scheme
69         MaxBlock=countblocks(scs_m);
70         //last created fictitious block (clock split,clock sum,super_blocks, superbloc))
71         cur_fictitious=MaxBlock
72         path=[];       // for delete_unconnected
73         scs_m_s=scs_m ;// for delete_unconnected
74     end
75     //-------------- suppress blocks with an unconnected regular port --------------
76     scs_m=delete_unconnected(scs_m);
77
78     //list of blocks with are not retained in the final block list
79     blocks_to_remove=["CLKSPLIT_f" "SPLIT_f" "IMPSPLIT_f" "CLKSOM_f" "CLKSOMV_f" "NRMSOM_f" "PAL_f" "xcos_block"]
80     port_blocks=["IN_f","INIMPL_f","OUT_f","OUTIMPL_f","CLKIN_f","CLKINV_f","CLKOUT_f","CLKOUTV_f"]
81     block_goto=["GOTO","CLKGOTO","GOTOMO"]
82     block_from=["FROM","CLKFROM","FROMMO"]
83     block_tag=["GotoTagVisibility","CLKGotoTagVisibility","GotoTagVisibilityMO"]
84     n=lstsize(scs_m.objs) //number of "objects" in the data structure
85     //-------------- initialize outputs --------------
86     nb=0;
87     links_table=[]; //
88     corinv=list();
89     cor=list();for k=1:n, cor(k)=0;end
90
91     ok=%t;
92     IN=[];OUT=[];EIN=[];EOUT=[];
93     Links=[] //to memorize links position in the data structure
94     mod_blk_exist=%f;
95     //-------------- Analyse blocks --------------
96     loc_mat=[];from_mat=[];tag_exprs=[];sco_mat=[];
97     for k=1:n //loop on all objects
98         o=scs_m.objs(k);
99         x=getfield(1,o);
100         cor(k)=0
101         if x(1)=="Block" then
102             if or(o.gui==block_goto) then
103                 cur_fictitious=cur_fictitious+1;
104                 cor(k)=-cur_fictitious;
105                 if (o.graphics.exprs(2)=="1") then
106                     loc_mat=[loc_mat;[string(cur_fictitious),string(1),(o.graphics.exprs(1)),string(find(block_goto(:)==o.gui))]]
107                     locomat=[];
108                     for i=1:size(loc_mat,1)
109                         locomat=[locomat;strcat([loc_mat(i,3) loc_mat(i,4)])]
110                     end
111                     vec=unique(locomat)
112                     if size(vec,1)<>size(loc_mat,1) then
113                         if flgcdgen<>-1 then path=[numk path];scs_m=all_scs_m; end
114                         if (ksup==0)|flgcdgen<>-1  then
115                             hilite_path([path,k],"There is another local GOTO in this diagram with the same tag ''"+loc_mat($,3)+"''",%t);
116                         else
117                             hilite_path([path,k], "There is another local GOTO in this diagram with the same tag ''"+loc_mat($,3)+"''",%t);
118                         end
119                         disp(mprintf("%s: goto tag not unique", "scicos_flat"));
120                         ok=%f;return
121                     end
122                 else
123                     sco_mat=[sco_mat;[string(cur_fictitious),string(1),o.graphics.exprs(1),o.graphics.exprs(2),string(find(block_goto(:)==o.gui))]]
124                 end
125             elseif or(o.gui==block_from) then
126                 cur_fictitious=cur_fictitious+1;
127                 cor(k)=-cur_fictitious
128                 sco_mat=[sco_mat;[string(cur_fictitious),string(-1),o.graphics.exprs(1),string(1),string(find(block_from(:)==o.gui))]]
129                 from_mat=[from_mat;[string(cur_fictitious),string(-1),o.graphics.exprs(1),string(find(block_from(:)==o.gui))]]
130             elseif or(o.gui==block_tag) then
131                 tag_exprs=[tag_exprs;[o.graphics.exprs(1),string(find(block_tag(:)==o.gui))]]
132                 cur_fictitious=cur_fictitious+1;
133                 cor(k)=-cur_fictitious
134             elseif o.gui=="SampleCLK" then
135                 if o.graphics.peout<>0 then
136                     cur_fictitious=cur_fictitious+1;
137                     cor(k)=-cur_fictitious
138                     [Nf,Df]=rat(o.model.rpar(1),1d-9);
139                     [No,Do]=rat(o.model.rpar(2),1d-9);
140                     sco_mat=[sco_mat;[string(cur_fictitious),string(1),string(Nf)+"/"+string(Df),..
141                     string(No)+"/"+string(Do),string(4)]]
142                 end
143                 //Adding the VirtualCLK0. Fady 18/11/2007
144             elseif o.gui=="VirtualCLK0" then
145                 cur_fictitious=cur_fictitious+1;
146                 cor(k)=-cur_fictitious
147                 sco_mat=[sco_mat;[string(cur_fictitious),string(1),"scicostimeclk0",..
148                 string(2),string(10)]]
149                 tag_exprs=[tag_exprs;["scicostimeclk0",string(10)]]
150             elseif or(o.gui==blocks_to_remove) then
151                 cur_fictitious=cur_fictitious+1;
152                 cor(k)=cur_fictitious
153             elseif o.gui=="SUM_f"|o.gui=="SOM_f" then
154                 nb=nb+1;
155                 corinv(nb)=k;
156                 cor(k)=nb
157                 //scs_m=adjust_sum(scs_m,k)
158             elseif or(o.gui==port_blocks) then
159                 //here we suppose to be inside a superblock
160                 //may be we can handle this blocks just as blocks_to_remove
161                 if ksup==0 then
162                     scs_m=scs_m_s
163                     hilite_path([path,k],gettext("I/O blocks must be only used in a Super Block"),%f)
164                     disp(mprintf("%s: Port out of hierarchy", "scicos_flat"));
165                     ok=%f;return
166                 end
167                 connected=get_connected(scs_m,k)
168                 if connected==[] then
169                     scs_m=scs_m_s
170                     hilite_path([path,k],gettext("This Super block input port is not connected."),%t)
171                     disp(mprintf("%s: Not connected super block input", "scicos_flat"));
172                     ok=%f;return
173                 end
174                 if or(o.gui==["IN_f","INIMPL_f"]) then
175                     pind=Pind(1)
176                     IN=[IN o.model.ipar]
177                 elseif or(o.gui==["OUT_f","OUTIMPL_f"]) then
178                     pind=Pind(2)
179                     OUT=[OUT o.model.ipar]
180                 elseif or(o.gui==["CLKIN_f","CLKINV_f"]) then
181                     pind=Pind(3)
182                     EIN=[EIN o.model.ipar]
183                 elseif or(o.gui==["CLKOUT_f","CLKOUTV_f"]) then
184                     pind=Pind(4)
185                     EOUT=[EOUT o.model.ipar]
186                 end
187                 //connect the link to the fictitious bloc replacing the superblock
188                 if scs_m.objs(connected).from(1)==k then
189                     scs_m.objs(connected).from(1)=-(pind+o.model.ipar)
190                 end
191                 if scs_m.objs(connected).to(1)==k then
192                     scs_m.objs(connected).to(1)=-(pind+o.model.ipar)
193                 end
194             elseif o.model.sim(1)=="asuper" then
195                 nb=nb+1
196                 corinv(nb)=k
197                 cor(k)=nb
198                 if o.graphics.exprs(3).dep_ut($)==%t then
199                     sco_mat=[sco_mat;[string(nb) "-1" "scicostimeclk0" "1" "10"]]
200                 end
201             elseif o.model.sim=="super"|o.model.sim=="csuper" then
202                 path=[path k] //superbloc path in the hierarchy
203                 //replace superbloc by a set of fictitious blocks (one per port)
204                 //and reconnect links connected to the superblock to these
205                 //ficitious blocks
206                 Pinds=[];if exists("Pind") then Pinds=Pind,end
207                 Pind=[] //base of ports numbering
208                 //mprintf("entering superblock at level "+string(size(path,'*'))+"\r\n")
209                 nb_pin=size(scs_m.objs(k).graphics("pin"),1);
210                 nb_pein=size(scs_m.objs(k).graphics("pein"),1);
211                 for port_type=["pin","pout","pein","peout"]
212                     Pind=[Pind cur_fictitious]
213                     ip=scs_m.objs(k).graphics(port_type);
214                     ki=find(ip>0)
215                     for kk=ki
216                         kc=ip(kk)
217                         //**  a link is connected to the same sblock on both ends
218                         if scs_m.objs(kc).to(1)==scs_m.objs(kc).from(1) then
219                             //** regular input port
220                             if port_type=="pin" then
221                                 scs_m.objs(kc).to(1)=-(cur_fictitious+scs_m.objs(kc).to(2));
222                                 scs_m.objs(kc).to(2)=1
223
224                                 if scs_m.objs(kc).from(3)==0 then //** in connected to out
225                                     scs_m.objs(kc).from(1)=-(cur_fictitious+scs_m.objs(kc).from(2)+nb_pin);
226                                     scs_m.objs(kc).from(2)=1
227                                 else //** in connected to in
228                                     scs_m.objs(kc).from(1)=-(cur_fictitious+scs_m.objs(kc).from(2));
229                                     scs_m.objs(kc).from(2)=1
230                                 end
231
232                                 //** regular output port
233                             elseif port_type=="pout" then
234                                 scs_m.objs(kc).from(1)=-(cur_fictitious+scs_m.objs(kc).from(2));
235                                 scs_m.objs(kc).from(2)=1
236
237                                 if scs_m.objs(kc).to(3)==0 then //** out connected to out
238                                     scs_m.objs(kc).to(1)=-(cur_fictitious+scs_m.objs(kc).to(2));
239                                     scs_m.objs(kc).to(2)=1
240                                 end
241
242                                 //** event input port
243                             elseif port_type=="pein" then
244                                 scs_m.objs(kc).to(1)=-(cur_fictitious+scs_m.objs(kc).to(2));
245                                 scs_m.objs(kc).to(2)=1
246
247                                 scs_m.objs(kc).from(1)=-(cur_fictitious+scs_m.objs(kc).from(2)+nb_pein);
248                                 scs_m.objs(kc).from(2)=1
249
250                                 //** peout and pein are never connected to themselves
251                             end
252
253                         elseif scs_m.objs(kc).to(1)==k then  // a link going to the superblock
254                             scs_m.objs(kc).to(1)=-(cur_fictitious+scs_m.objs(kc).to(2));
255                             scs_m.objs(kc).to(2)=1
256
257                         elseif scs_m.objs(kc).from(1)==k then  // a link coming from the superblock
258                             scs_m.objs(kc).from(1)=-(cur_fictitious+scs_m.objs(kc).from(2));
259                             scs_m.objs(kc).from(2)=1
260                         end
261                     end
262                     cur_fictitious=cur_fictitious+size(ip,"*")
263                 end
264
265
266                 //Analyze the superblock contents
267                 [cors,corinvs,lt,cur_fictitious,scop_mat,ok, localIN, localOUT, localEIN, localEOUT]=scicos_flat(o.model.rpar,cur_fictitious,MaxBlock)
268                 if ~ok then
269                     disp(mprintf("%s: Invalid super block at %d", "scicos_flat", k));
270                     return
271                 end
272
273                 // check if the ports has the right order
274                 localIN=-gsort(-localIN);
275                 if or(localIN<>[1:size(localIN,"*")]) then
276                     ok=%f;
277                     msg=gettext("Input ports are not numbered properly.")
278                     hilite_path(path,msg,%t)
279                     disp(mprintf("%s: Input ports are not numbered properly.", "scicos_flat"))
280                     return
281                 end
282                 localOUT=-gsort(-localOUT);
283                 if or(localOUT<>[1:size(localOUT,"*")]) then
284                     ok=%f;
285                     msg=gettext("Output ports are not numbered properly.")
286                     hilite_path(path,msg,%t)
287                     disp(mprintf("%s: Output ports are not numbered properly.", "scicos_flat"))
288                     return
289                 end
290                 localEIN=-gsort(-localEIN);
291                 if or(localEIN<>[1:size(localEIN,"*")]) then
292                     ok=%f;
293                     msg=gettext("Event input ports are not numbered properly.")
294                     hilite_path(path,msg,%t)
295                     disp(mprintf("%s: Event input ports are not numbered properly.", "scicos_flat"))
296                     return
297                 end
298                 localEOUT=-gsort(-localEOUT);
299                 if or(localEOUT<>[1:size(localEOUT,"*")]) then
300                     ok=%f;
301                     msg=gettext("Event output ports are not numbered properly.")
302                     hilite_path(path,msg,%t)
303                     disp(mprintf("%s: Event output ports are not numbered properly.", "scicos_flat"))
304                     return
305                 end
306
307                 //shifting the scop_mat for regular blocks. Fady 08/11/2007
308                 if scop_mat<>[] then
309                     v_mat=find(eval(scop_mat(:,1))<MaxBlock)
310                     v_mat=v_mat(:)
311                     for j=v_mat
312                         scop_mat(j,1)=string(eval(scop_mat(j,1))+nb)
313                     end
314                 end
315                 //Adding the scop_mat to the old sco_mat.
316                 sco_mat=[sco_mat;scop_mat]
317                 nbs=size(corinvs)
318
319                 //catenate superbloc data with current data
320
321                 f=find(lt(:,1)>0&lt(:,1)<=nbs);if f<>[] then lt(f,1)=lt(f,1)+nb,end
322                 links_table=[links_table;lt]
323
324                 for kk=1:nbs, corinv(nb+kk)=[k,corinvs(kk)];end
325                 cors=shiftcors(cors,nb)
326                 //      cur_fictitious=cur_fictitious+nb
327                 cor(k)=cors
328                 nb=nb+nbs
329                 Pind=Pinds
330                 path($)=[]
331
332             else //standard blocks
333                 nb=nb+1
334                 corinv(nb)=k
335                 //[model,ok]=build_block(o.model)
336                 cor(k)=nb
337                 //Adding the always activated blocks to the sco_mat to take care of the enabling if exists.
338                 //Fady 18/11/2007
339                 if ~is_modelica_block(o) then
340                     if o.model.dep_ut($) then
341                         sco_mat=[sco_mat;[string(nb) "-1" "scicostimeclk0" "1" "10"]]
342                     end
343                 else
344                     mod_blk_exist=%t // Flag for the existance of modelica's blocks
345                 end
346             end
347         elseif x(1)=="Deleted"|x(1)=="Text" then
348             //this objects are ignored
349         else //links
350             Links=[Links k] // memorize their position for use during links analysis
351         end
352     end //end of loop on objects
353
354     if ksup==0&nb==0 then
355         messagebox(msprintf(gettext("%s: Empty diagram"), "Xcos"),"modal")
356         ok=%f
357         disp(msprintf("%s: Empty diagram", "scicos_flat"));
358         return
359     end
360     //-------------- Analyse  links --------------
361     for k=Links
362         o=scs_m.objs(k);
363         f=0
364         if o.from(1)<0|o.from(1)>MaxBlock then //Link coming from a superblock input port
365         else
366             o.from(1)=cor(o.from(1));
367         end
368         if o.to(1)<0 |o.to(1)>MaxBlock then //Link going to a superblock output port
369         else
370             o.to(1)=cor(o.to(1)),
371         end
372
373         if o.ct(2)==2 //implicit links
374             //if abs(o.from(1))==125|abs(o.to(1))==125 then pause,end
375             links_table=[links_table
376             o.from(1:3)    o.ct(2)
377             o.to(1:3)      o.ct(2) ]
378         else //regular or event links
379             links_table=[links_table
380             o.from(1:2)  -1  o.ct(2) //outputs are tagged with -1
381             o.to(1:2)    1   o.ct(2) ] //inputs are tagged with 1
382         end
383     end
384     // Warning in case of modelica's blocks in an enabled diagram.
385     // Fady 18/11/2007
386     tof=find((sco_mat(:,2)=="1")& (sco_mat(:,5)=="10"))
387     if tof<>[] then
388         if mod_blk_exist then
389             messagebox("Warning the enable does not consider the modelica blocks","modal")
390         end
391     end
392     //----------------------Goto From Analyses--------------------------
393     // Local case
394     if loc_mat<>[] then
395         for i=1:size(loc_mat,1)
396             index1=find((from_mat(:,2)=="-1")&(from_mat(:,3)==loc_mat(i,3))&(from_mat(:,4)==loc_mat(i,4)))
397             for j=index1
398                 index2=find(links_table(:,1)==-evstr(from_mat(j,1)))
399                 //           for k=index2
400                 //                links_table(k,1)=-evstr(loc_mat(i,1))
401                 //           end
402                 if index2<>[] then
403                     links_table(index2',1)=-evstr(loc_mat(i,1))
404                 end
405                 index2=find(sco_mat(:,1)==from_mat(j,1))
406                 sco_mat(index2',:)=[]
407             end
408         end
409     end
410     //scoped case
411     if tag_exprs<>[] then
412         //to be modified !!!!!
413         //      vec=unique(tag_exprs)
414         for i=1:size(tag_exprs,1)
415             index=find((tag_exprs(:,1)==tag_exprs(i,1))&(tag_exprs(:,2)==tag_exprs(i,2)))
416             if size(index,"*") > 1  then
417                 messagebox(["Error In Compilation. You cannot have multiple GotoTagVisibility";..
418                 " with the same tag value in the same scs_m"],"modal")
419                 ok=%f;
420                 disp(mprintf("%s: Multiple GotoTagVisibility at the same level", "scicos_flat"));
421                 return
422             end
423         end
424
425         for i=1:size(tag_exprs,1)
426             index=find((sco_mat(:,2)=="1")&(sco_mat(:,3)==tag_exprs(i,1))&(sco_mat(:,4)=="2")&(sco_mat(:,5)==tag_exprs(i,2)))
427             if index<>[] then
428                 if size(index,"*")>1 then
429                     messagebox(["Error in compilation";"Multiple GOTO are taged by the same GotoTagVisibility"],"modal")
430                     ok=%f
431                     disp(mprintf("%s: Shared GotoTagVisibility across GOTO", "scicos_flat"));
432                     return
433                 end
434                 index1=find((sco_mat(:,2)=="-1")&(sco_mat(:,3)==tag_exprs(i,1))&(sco_mat(:,5)==tag_exprs(i,2)))
435                 if index1<>[] then
436                     for j=index1
437                         index2=find(links_table(:,1)==-evstr(sco_mat(j,1)))
438                         if index2<>[] then
439                             links_table(index2',1)=-evstr(sco_mat(index,1))
440                         end
441                         //linking the always active blocks to the VirtualCLK0 if exists.
442                         if sco_mat(j,5)=="10" then
443                             links_table($+1,:)=[-evstr(sco_mat(index,1)) 1 -1 -1]
444                             links_table($+1,:)=[evstr(sco_mat(j,1)) 0 1 -1]
445                         end
446                     end
447                 end
448                 sco_mat([index1';index'],:)=[]
449                 //sco_mat(index,:)=[]
450             end
451         end
452     end
453     //global case
454     // function global_case in c_pass1
455     //------------------------------------------------------------------------
456 endfunction