Scicos: indent c_pass1 and related modelica files
[scilab.git] / scilab / modules / scicos / macros / scicos_scicos / c_pass1.sci
1 //  Scicos
2 //
3 //  Copyright (C) INRIA - METALAU Project <scicos@inria.fr>
4 //                      - Serge Steer <serge.steer@inria.fr>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 //
20 // See the file ../license.txt
21 //
22
23 function  [blklst,cmat,ccmat,cor,corinv,ok,scs_m,flgcdgen,freof]=c_pass1(scs_m,flgcdgen)
24     //derived from c_pass1 for implicit diagrams
25     //%Purpose
26     // Determine one level blocks and connections matrix
27     //%Parameters
28     // scs_m  :   scicos data structure
29     // ksup   :
30     // blklst : a list containing the "model" information structure for each block
31     //
32     // cmat   : nx6 matrix. Each row contains, in order, the block
33     //             number and the port number and the port type of an outgoing scicopath,
34     //             and the block number and the port number and the port type of the target
35     //             ingoing scicopath. for regular links
36     //
37     // ccmat  : nx4 matrix.  Each row contains, in order, the block
38     //             number and the port number  of an outgoing scicopath,
39     //             and the block number and the port number  of the target
40     //             ingoing scicopath for clock connections
41
42     // cor    : is a list with same recursive structure as scs_m each leaf
43     //          contains the index of associated block in blklst
44     // corinv : corinv(nb) is the path of nb ith block defined in blklst
45     //          in the scs_m structure
46     //!
47     // Serge Steer 2003, Copyright INRIA
48     // flgcdgen: is a flag containing the numbre of event input of the diagram
49     //           it is used only in the Codegeneration case.
50     // freof   : it is a vector containing the frequency and the offset of the major clock.
51     //           it is used only in the Codegeneration case.
52     // Fady Nassif 2007. INRIA.
53     //c_pass1;
54
55     if argn(2)<=1 then flgcdgen=-1, end
56     freof=[];
57     MaxBlock=countblocks(scs_m);
58     blklst=[];cmat=[],ccmat=[],cor=[],corinv=[]
59     [cor,corinvt,links_table,cur_fictitious,sco_mat,ok]=scicos_flat(scs_m);
60     if ~ok then
61         disp(mprintf("%s: flat failed", "c_pass1"));
62         return;
63     end
64     [links_table,sco_mat,ok]=global_case(links_table,sco_mat)
65     if ~ok then
66         disp(mprintf("%s: global case failed", "c_pass1"));
67         return;
68     end
69     index1=find((sco_mat(:,2)=="-1")& (sco_mat(:,5)<>"10"))
70     if index1<>[] then
71         for i=index1
72             [path]=findinlist(cor,-evstr(sco_mat(i,1)))
73             full_path=path(1)
74             if flgcdgen<>-1 then full_path=[numk full_path];scs_m=all_scs_m;end
75             hilite_path(full_path,"Error in compilation, There is a FROM ''"+(sco_mat(i,3))+ "'' without a GOTO",%t)
76             ok=%f;
77             disp(mprintf("%s: invalid connection matrix", "c_pass1"));
78             return;
79         end
80     end
81
82     nb=size(corinvt);
83     reg=1:nb
84     //form the block lists
85
86     blklst=list();kr=0 ; //regular  block list
87     blklstm=list();km=0; //modelica block list
88
89     //if ind(i)>0  ith block is a regular  block and stored in blklst(ind(i))
90     //if ind(i)<0  ith block is a modelica block and stored in blklstm(-ind(i))
91
92     ind=[];
93
94     for kb=1:nb
95         o=scs_m(scs_full_path(corinvt(kb)));
96         if is_modelica_block(o) then
97             km=km+1;blklstm(km)=o.model;
98             ind(kb)=-km;
99             [modelx,ok]=build_block(o); // compile modelica block type 30004
100             if ~ok then
101                 disp(mprintf("%s: unable to build modelica block", "c_pass1"));
102                 return
103             end
104         else
105             [model,ok]=build_block(o);
106             if ~ok then
107                 disp(mprintf("%s: unable to build block", "c_pass1"));
108                 return,
109             end
110
111             if or(model.sim(1)==["plusblk"]) then
112                 [model,links_table]=adjust_sum(model,links_table,kb);
113             end
114
115             kr=kr+1;blklst(kr)=model;
116             ind(kb)=kr;
117         end
118
119     end
120
121     if (find(sco_mat(:,5)==string(4))<>[]) then
122         if flgcdgen ==-1 then
123             [links_table,blklst,corinvt,ind,ok]=sample_clk(sco_mat,links_table,blklst,corinvt,scs_m,ind,flgcdgen)
124         else
125             [links_table,blklst,corinvt,ind,ok,scs_m,flgcdgen,freof]=sample_clk(sco_mat,links_table,blklst,corinvt,scs_m,ind,flgcdgen)
126         end
127         if ~ok then
128             disp(mprintf("%s: unable to sample the whole diagram", "c_pass1"));
129             return,
130         end
131     end
132     nb=size(corinvt)
133     nl=size(links_table,1)/2
134
135     // Check if size match !
136     if(size(links_table(:,1:3), "r") == size(matrix([1;1]*(1:nl),-1,1), "r") ..
137         & size(matrix([1;1]*(1:nl),-1,1), "r") == size(links_table(:,4), "r"))
138         links_table=[links_table(:,1:3) matrix([1;1]*(1:nl),-1,1) ..
139         links_table(:,4) ];
140     else
141         disp(mprintf("%s: invalid links table size", "c_pass1"));
142         return
143     end
144     imp=find(ind<0)
145
146     reg(imp)=[]
147
148     if imp==[] then //no modelica block exists
149         cmat=matfromT(links_table(find(links_table(:,5)==1),:),nb); //data flow links
150         ccmat=cmatfromT(links_table(find(links_table(:,5)==-1),:),nb); //event links
151         corinv=corinvt
152     else // mixed diagram
153         nm=size(imp,"*") //number of modelica blocks
154         nr=nb-nm //number of regular blocks
155         cmmat=mmatfromT(links_table(find(links_table(:,5)==2),:),nb); //modelica links
156         cmat=matfromT(links_table(find(links_table(:,5)==1),:),nb); //data flow links
157         ccmat=cmatfromT(links_table(find(links_table(:,5)==-1),:),nb);//event links
158         //build connections between modelica world and regular one. These
159         //links should be data flow links
160         // links from modelica world to regular world
161         fromM=find(dsearch(cmat(:,1),imp,"d")>0);NoM=size(fromM,"*");
162
163         if NoM>0 then
164             //add modelica Output ports in Modelica world
165             mo=modelica();mo.model="OutPutPort";mo.outputs="vo";mo.inputs="vi";
166             for k=1:NoM,blklstm($+1)=scicos_model(equations=mo);end
167             //add modelica connections to these Output ports, set negative
168             //value to port numbers to avoid conflits with other blocks
169             cmmat=[cmmat;
170             cmat(fromM,1:2) zeros(NoM,1) -(nm+(1:NoM)'),ones(NoM,1),ones(NoM,1)];
171
172             nm=nm+NoM;
173
174             //add regular connection with regular block replacing the modelica world
175
176             cmat(fromM,1:2)=[-(nr+1)*ones(NoM,1),(1:NoM)'];
177         end
178
179         // links from regular world to modelica world
180         toM=find(dsearch(cmat(:,3),imp,"d")>0);NiM=size(toM,"*");
181         if NiM>0 then
182             //add modelica Input ports in Modelica world
183             mo=modelica();mo.model="InPutPort";mo.outputs="vo";mo.inputs="vi";
184             for k=1:NiM,blklstm($+1)=scicos_model(equations=mo);end
185             //add modelica connections to these Input ports  set negative
186             //value to port numbers to avoid conflits with other blocks
187             cmmat=[cmmat;
188             -(nm+(1:NiM)'), ones(NiM,1),zeros(NiM,1), cmat(toM,3:4), ones(NiM,1) ];
189
190             nm=nm+NiM;
191             //add regular connection with regular block replacing the modelica world
192             cmat(toM,3:4)=[-(nr+1)*ones(NiM,1),(1:NiM)'];
193         end
194
195         // modelica blocks with events ports are not allowed yet
196         if size(ccmat,1)>0 then
197             if or(dsearch(ccmat(:,[1 3]),imp,"d")>0) then
198                 messagebox("An implicit block has an event port","modal","error");
199                 disp(mprintf("%s: implicit block with event port", "c_pass1"));
200                 ok=%f;return
201             end
202         end
203
204         //renumber blocks according to their types
205
206         corinv=list();corinvm=list();
207
208         for kb=1:nb
209
210             if ind(kb)<0 then // modelica block
211
212                 km=-ind(kb);
213
214                 //replace by negative value to avoid conflicts
215
216                 cmmat(find(cmmat(:,1)==kb),1)=-km ;
217
218                 cmmat(find(cmmat(:,4)==kb),4)=-km;
219
220                 corinvm(km)=corinvt(kb);
221
222             else
223
224                 kr=ind(kb);
225
226                 cmat (find(cmat (:,1)==kb),1)=-kr;
227
228                 cmat (find(cmat (:,3)==kb),3)=-kr;
229
230                 ccmat(find(ccmat(:,1)==kb),1)=-kr;
231
232                 ccmat(find(ccmat(:,3)==kb),3)=-kr;
233
234                 corinv(kr)=corinvt(kb);
235
236             end
237
238         end
239
240         //renumbering done, replace negative value by positive ones
241
242
243
244         cmat(:,[1 3])=abs(cmat(:,[1 3])) ;
245
246         ccmat(:,[1 3])=abs(ccmat(:,[1 3])) ;
247
248         cmmat=abs(cmmat) ;
249
250         //create regular block associated to all modelica blocks
251
252         [model,ok]=build_modelica_block(blklstm,corinvm,cmmat,NiM,NoM,scs_m,TMPDIR+"/");
253
254         if ~ok then
255             disp(mprintf("%s: build the modelica meta-block failed", "c_pass1"));
256             return
257         end
258
259         blklst(nr+1)=model;
260
261         //make compiled modelica block refer to the set of corresponding
262
263         //modelica blocks
264
265         corinv(nr+1)=corinvm //it may be useful to adapt function making use
266
267         //of corinv
268
269         //adjust the numbering of regular block in sco_mat
270
271         //if modelica's blocks exist
272
273         //Fady 08/11/2007
274
275         for i=1:size(sco_mat,1)
276
277             if eval(sco_mat(i,1))<MaxBlock then
278
279                 sco_mat(i,1)=string(ind(eval(sco_mat(i,1))))
280
281             end
282
283         end
284
285         sco_mat=[sco_mat;[string(size(blklst)) "-1" "scicostimeclk0" "1" "10"]]
286
287     end
288
289     cor=update_cor(cor,reg)
290
291
292
293     // Taking care of the clk 0;
294
295     //*** this part has been taken from c_pass2 modified and placed here it must be tested ***
296
297     //Fady 08/11/2007
298
299     nbl=size(blklst)
300
301     fff=ones(nbl,1)==1
302
303     clkptr=zeros(nbl+1,1);clkptr(1)=1; typ_l=fff;
304
305     for i=1:nbl
306
307         ll=blklst(i);
308
309         clkptr(i+1)=clkptr(i)+size(ll.evtout,"*");
310
311         //tblock(i)=ll.dep_ut($);
312
313         typ_l(i)=ll.blocktype=="l";
314
315     end
316
317     all_out=[]
318
319     for k=1:size(clkptr,1)-1
320
321         if ~typ_l(k) then
322
323             kk=[1:(clkptr(k+1)-clkptr(k))]'
324
325             all_out=[all_out;[k*ones(kk),kk]]
326
327         end
328
329     end
330
331     all_out=[all_out;[0,0]]
332     //add time event if needed
333     tblock=find((sco_mat(:,2)=="-1")&(sco_mat(:,5)=="10"))
334     ind=sco_mat(tblock,1);
335     if ind<>[] then
336         ind=eval(ind(:))
337         //ind=find(tblock)
338         //ind=ind(:)
339         for k=ind'
340             ccmat=[ccmat;[all_out,ones(all_out)*[k,0;0,0]]]
341         end
342         for Ii=1:length(blklst)
343             if type(blklst(Ii).sim(1))==10 then
344                 if part(blklst(Ii).sim(1),1:7)=="capteur" then
345                     ccmat=[ccmat;[0 0 Ii 0]]
346                 end
347             end
348         end
349     end
350     //***
351 endfunction
352 //**-----------------------------------------------------------------------------------------------------------------
353
354 function [model,links_table]=adjust_sum(model,links_table,k)
355     //sum blocks have variable number of input ports, adapt the associated
356     //model data structure and input connection to take into account the
357     //actual number of connected ports
358     // Serge Steer 2003, Copyright INRIA
359     in=find(links_table(:,1)==k&links_table(:,3)==1)
360     nin=size(in,"*")
361     model.in=-ones(nin,1)
362     links_table(in,2)=(1:nin)'
363 endfunction
364
365
366 function mat=mmatfromT(Ts,nb)
367     //S. Steer, R. Nikoukhah 2003. Copyright INRIA
368     Ts(:,1)=abs(Ts(:,1));
369     K=unique(Ts(find(Ts(:,1)>nb),1)); // identificator of blocks to be removed
370     //remove superblocks port and split connections
371     Ts=remove_fictitious(Ts,K)
372
373     // from connection matrix
374     Imat=[];
375     for u=matrix(unique(Ts(:,4)),1,-1)
376         kue=matrix(find(Ts(:,4)==u),-1,1); //identical links
377         Imat=[Imat;[kue(2:$)  kue(1).*ones(kue(2:$))]];
378     end
379     mat=[Ts(Imat(:,1),1:3)  Ts(Imat(:,2),1:3)]
380 endfunction
381
382
383 function mat=matfromT(Ts,nb)
384     //S. Steer, R. Nikoukhah 2003. Copyright INRIA
385
386     Ts(:,1)=abs(Ts(:,1))
387     K=unique(Ts(find(Ts(:,1)>nb),1)); // identificator of blocks to be removed
388     //remove superblocks port and split connections
389     Ts=remove_fictitious(Ts,K)
390
391     // from connection matrix
392     Imat=[];
393     for u=matrix(unique(Ts(:,4)),1,-1)
394         kue=matrix(find(Ts(:,4)==u&Ts(:,3)==-1),-1,1); //look for outputs
395         jue=matrix(find(Ts(:,4)==u&Ts(:,3)==1),-1,1); //look for inputs
396         Imat=[Imat;[ones(jue).*.kue jue.*.ones(kue)]];
397     end
398     mat=[Ts(Imat(:,1),1:2)  Ts(Imat(:,2),1:2)]
399 endfunction
400
401 function mat=cmatfromT(Ts,nb)
402     //S. Steer, R. Nikoukhah 2003. Copyright INRIA
403     //this function has been modified to support
404     // CLKGOTO et CLKFROM
405     // Fady NASSIF: 11/07/2007
406     k=find(Ts(:,1)<0) //superblock ports links and CLKGOTO/CLKFROM
407     K=unique(Ts(k,1));
408     Ts=remove_fictitious(Ts,K)
409
410     if Ts==[] then mat=[],return,end
411     //  if size(Ts,1)<>int(size(Ts,1)/2)*2 then disp('PB'),pause,end
412     [s,k]=gsort(Ts(:,[4,3]),"lr","i");Ts=Ts(k,:)
413     // modified to support the CLKGOTO/CLKFROM
414     //mat=[Ts(1:2:$,1:2) Ts(2:2:$,1:2)]
415     //----------------------------------
416
417     J=find(Ts(:,3)==1); //find the destination block of the link
418     v=find([Ts(:,3);-1]==-1) // find the source block of the link
419     // many destination blocks can be connected to one source block
420     // so we have to find the number of destination blocks for each source block
421     // v(2:$)-v(1:$-1)-1
422     // then create the vector I that must be compatible with the vector J.
423     I=duplicate(v(1:$-1),v(2:$)-v(1:$-1)-1);
424     mat=[Ts(I,1:2),Ts(J,1:2)]
425
426     //----------------------------------
427     K=unique(Ts(Ts(:,1)>nb))
428     Imat=[];
429     for u=matrix(K,1,-1)
430         jue=matrix(find(mat(:,1)==u),-1,1); //look for outputs
431         kue=matrix(find(mat(:,3)==u),-1,1); //look for inputs
432         Imat=[ones(jue).*.kue jue.*.ones(kue)];
433         mat1=[mat(Imat(:,1),1:2), mat(Imat(:,2),3:4)];
434         mat([jue;kue],:)=[];
435         mat=[mat;mat1];
436     end
437
438 endfunction
439
440 function Ts=remove_fictitious(Ts,K)
441     //removes fictitious blocks connected links are replaced by a single one
442     //S. Steer, R. Nikoukhah 2003. Copyright INRIA
443     count=min(Ts(:,4))
444     for i=1:size(K,"*")
445         ki=K(i);
446         v1=find(Ts(:,1)==ki);
447         if v1<>[] then
448             v=unique(Ts(v1,4));
449             Ts(v1,:)=[];
450             if size(v)==1 then
451                 ind=find(Ts(:,4)==v);
452             else
453                 ind = find(dsearch(Ts(:,4),gsort(v,"g","i"),"d")<>0);
454             end
455             if size(ind,"*")>1 then
456                 count=count-1;
457                 Ts(ind,4)=count
458             else
459                 Ts(ind,:)=[]
460             end
461         end
462     end
463 endfunction
464
465 function cor=update_cor(cor,reg)
466     n=size(cor)
467     for k=1:n
468         if type(cor(k))==15 then
469             cor(k)=update_cor(cor(k),reg)
470         else
471             p=find(cor(k)==reg)
472             if p<>[] then
473                 cor(k)=p
474             elseif cor(k)<0 then  // GOTO FROM cases
475                 cor(k)=0
476             elseif cor(k)<>0 then
477                 cor(k)=size(reg,"*")+1
478             end
479         end
480     end
481 endfunction