b683a193e5287d9a7b62e9932848b4be4ea7cf1f
[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