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
23function  [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(msprintf("%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(msprintf("%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(msprintf("%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(msprintf("%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(msprintf("%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(msprintf("%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(msprintf("%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
159        //build connections between modelica world and regular one. These
160        //links should be data flow links
161        // links from modelica world to regular world
162        fromM=find(dsearch(cmat(:,1),imp,"d")>0);
163
164        // links from regular world to modelica world
165        toM=find(dsearch(cmat(:,3),imp,"d")>0);
166
167        // merge the modelica to modelica as data flow links
168        [varM, kfrom, kto] = intersect(fromM, toM);
169        fromM(kfrom) = [];
170        toM(kto) = [];
171
172        NoM=size(fromM,"*");
173        if NoM>0 then
174            //add modelica Output ports in Modelica world
175            mo=modelica();mo.model="OutPutPort";mo.outputs="vo";mo.inputs="vi";
176            for k=1:NoM,blklstm($+1)=scicos_model(equations=mo);end
177            //add modelica connections to these Output ports, set negative
178            //value to port numbers to avoid conflits with other blocks
179            cmmat=[cmmat;
180            cmat(fromM,1:2) zeros(NoM,1) -(nm+(1:NoM)'),ones(NoM,1),ones(NoM,1)];
181
182            nm=nm+NoM;
183            //add regular connection with regular block replacing the modelica world
184            cmat(fromM,1:2)=[-(nr+1)*ones(NoM,1),(1:NoM)'];
185        end
186
187        NiM=size(toM,"*");
188        if NiM>0 then
189            //add modelica Input ports in Modelica world
190            mo=modelica();mo.model="InPutPort";mo.outputs="vo";mo.inputs="vi";
191            for k=1:NiM,blklstm($+1)=scicos_model(equations=mo);end
192            //add modelica connections to these Input ports  set negative
193            //value to port numbers to avoid conflits with other blocks
194            cmmat=[cmmat;
195            -(nm+(1:NiM)'), ones(NiM,1),zeros(NiM,1), cmat(toM,3:4), ones(NiM,1) ];
196
197            nm=nm+NiM;
198            //add regular connection with regular block replacing the modelica world
199            cmat(toM,3:4)=[-(nr+1)*ones(NiM,1),(1:NiM)'];
200        end
201
202        NvM=size(varM, "*");
203        if NvM>0 then
204            //add modelica Values (both input and output) ports in Modelica world
205            l=[cmat(varM,1:2), zeros(NvM,1), cmat(varM,3:4), ones(NvM,1)];
206            cmmat=[cmmat;
207            l];
208
209            // remove the corresponding explicit link
210            cmat(varM, :) = [];
211        end
212
213        // modelica blocks with events ports are not allowed yet
214        if size(ccmat,1)>0 then
215            if or(dsearch(ccmat(:,[1 3]),imp,"d")>0) then
216                messagebox("An implicit block has an event port","modal","error");
217                disp(msprintf("%s: implicit block with event port", "c_pass1"));
218                ok=%f;return
219            end
220        end
221
222        //renumber blocks according to their types
223
224        corinv=list();corinvm=list();
225
226        for kb=1:nb
227
228            if ind(kb)<0 then // modelica block
229
230                km=-ind(kb);
231
232                //replace by negative value to avoid conflicts
233
234                cmmat(find(cmmat(:,1)==kb),1)=-km ;
235
236                cmmat(find(cmmat(:,4)==kb),4)=-km;
237
238                corinvm(km)=corinvt(kb);
239
240            else
241
242                kr=ind(kb);
243
244                cmat (find(cmat (:,1)==kb),1)=-kr;
245
246                cmat (find(cmat (:,3)==kb),3)=-kr;
247
248                ccmat(find(ccmat(:,1)==kb),1)=-kr;
249
250                ccmat(find(ccmat(:,3)==kb),3)=-kr;
251
252                corinv(kr)=corinvt(kb);
253
254            end
255
256        end
257
258        //renumbering done, replace negative value by positive ones
259
260
261
262        cmat(:,[1 3])=abs(cmat(:,[1 3])) ;
263
264        ccmat(:,[1 3])=abs(ccmat(:,[1 3])) ;
265
266        cmmat=abs(cmmat) ;
267
268        //create regular block associated to all modelica blocks
269
270        [model,ok]=build_modelica_block(blklstm,corinvm,cmmat,NiM,NoM,NvM,scs_m,TMPDIR+"/");
271
272        if ~ok then
273            disp(msprintf("%s: build the modelica meta-block failed", "c_pass1"));
274            return
275        end
276
277        blklst(nr+1)=model;
278
279        //make compiled modelica block refer to the set of corresponding
280
281        //modelica blocks
282
283        corinv(nr+1)=corinvm //it may be useful to adapt function making use
284
285        //of corinv
286
287        //adjust the numbering of regular block in sco_mat
288
289        //if modelica's blocks exist
290
291        //Fady 08/11/2007
292
293        for i=1:size(sco_mat,1)
294
295            if evstr(sco_mat(i,1))<MaxBlock then
296
297                sco_mat(i,1)=string(ind(evstr(sco_mat(i,1))))
298
299            end
300
301        end
302
303        sco_mat=[sco_mat;[string(size(blklst)) "-1" "scicostimeclk0" "1" "10"]]
304
305    end
306
307    cor=update_cor(cor,reg)
308
309
310
311    // Taking care of the clk 0;
312
313    //*** this part has been taken from c_pass2 modified and placed here it must be tested ***
314
315    //Fady 08/11/2007
316
317    nbl=size(blklst)
318
319    fff=ones(nbl,1)==1
320
321    clkptr=zeros(nbl+1,1);clkptr(1)=1; typ_l=fff;
322
323    for i=1:nbl
324
325        ll=blklst(i);
326
327        clkptr(i+1)=clkptr(i)+size(ll.evtout,"*");
328
329        //tblock(i)=ll.dep_ut($);
330
331        typ_l(i)=ll.blocktype=="l";
332
333    end
334
335    all_out=[]
336
337    for k=1:size(clkptr,1)-1
338
339        if ~typ_l(k) then
340
341            kk=[1:(clkptr(k+1)-clkptr(k))]'
342
343            all_out=[all_out;[k*ones(kk),kk]]
344
345        end
346
347    end
348
349    all_out=[all_out;[0,0]]
350    //add time event if needed
351    tblock=find((sco_mat(:,2)=="-1")&(sco_mat(:,5)=="10"))
352    ind=sco_mat(tblock,1);
353    if ind<>[] then
354        ind = evstr(ind(:))
355        //ind=find(tblock)
356        //ind=ind(:)
357        for k=ind'
358            ccmat=[ccmat;[all_out,ones(all_out)*[k,0;0,0]]]
359        end
360        for Ii=1:length(blklst)
361            if type(blklst(Ii).sim(1))==10 then
362                if part(blklst(Ii).sim(1),1:7)=="capteur" then
363                    ccmat=[ccmat;[0 0 Ii 0]]
364                end
365            end
366        end
367    end
368    //***
369endfunction
370//**-----------------------------------------------------------------------------------------------------------------
371
372function [model,links_table]=adjust_sum(model,links_table,k)
373    //sum blocks have variable number of input ports, adapt the associated
374    //model data structure and input connection to take into account the
375    //actual number of connected ports
376    // Serge Steer 2003, Copyright INRIA
377    in=find(links_table(:,1)==k&links_table(:,3)==1)
378    nin=size(in,"*")
379    model.in=-ones(nin,1)
380    links_table(in,2)=(1:nin)'
381endfunction
382
383
384function mat=mmatfromT(Ts,nb)
385    //S. Steer, R. Nikoukhah 2003. Copyright INRIA
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),-1,1); //identical links
395        Imat=[Imat;[kue(2:$)  kue(1).*ones(kue(2:$))]];
396    end
397    mat=[Ts(Imat(:,1),1:3)  Ts(Imat(:,2),1:3)]
398endfunction
399
400
401function mat=matfromT(Ts,nb)
402    //S. Steer, R. Nikoukhah 2003. Copyright INRIA
403
404    Ts(:,1)=abs(Ts(:,1))
405    K=unique(Ts(find(Ts(:,1)>nb),1)); // identificator of blocks to be removed
406    //remove superblocks port and split connections
407    Ts=remove_fictitious(Ts,K)
408
409    // from connection matrix
410    Imat=[];
411    for u=matrix(unique(Ts(:,4)),1,-1)
412        kue=matrix(find(Ts(:,4)==u&Ts(:,3)==-1),-1,1); //look for outputs
413        jue=matrix(find(Ts(:,4)==u&Ts(:,3)==1),-1,1); //look for inputs
414        Imat=[Imat;[ones(jue).*.kue jue.*.ones(kue)]];
415    end
416    mat=[Ts(Imat(:,1),1:2)  Ts(Imat(:,2),1:2)]
417endfunction
418
419function mat=cmatfromT(Ts,nb)
420    //S. Steer, R. Nikoukhah 2003. Copyright INRIA
421    //this function has been modified to support
422    // CLKGOTO et CLKFROM
423    // Fady NASSIF: 11/07/2007
424    k=find(Ts(:,1)<0) //superblock ports links and CLKGOTO/CLKFROM
425    K=unique(Ts(k,1));
426    Ts=remove_fictitious(Ts,K)
427
428    if Ts==[] then mat=[],return,end
429    //  if size(Ts,1)<>int(size(Ts,1)/2)*2 then disp('PB'),pause,end
430    [s,k]=gsort(Ts(:,[4,3]),"lr","i");Ts=Ts(k,:)
431    // modified to support the CLKGOTO/CLKFROM
432    //mat=[Ts(1:2:$,1:2) Ts(2:2:$,1:2)]
433    //----------------------------------
434
435    J=find(Ts(:,3)==1); //find the destination block of the link
436    v=find([Ts(:,3);-1]==-1) // find the source block of the link
437    // many destination blocks can be connected to one source block
438    // so we have to find the number of destination blocks for each source block
439    // v(2:$)-v(1:$-1)-1
440    // then create the vector I that must be compatible with the vector J.
441    I=duplicate(v(1:$-1),v(2:$)-v(1:$-1)-1);
442    mat=[Ts(I,1:2),Ts(J,1:2)]
443
444    //----------------------------------
445    K=unique(Ts(Ts(:,1)>nb))
446    Imat=[];
447    for u=matrix(K,1,-1)
448        jue=matrix(find(mat(:,1)==u),-1,1); //look for outputs
449        kue=matrix(find(mat(:,3)==u),-1,1); //look for inputs
450        Imat=[ones(jue).*.kue jue.*.ones(kue)];
451        mat1=[mat(Imat(:,1),1:2), mat(Imat(:,2),3:4)];
452        mat([jue;kue],:)=[];
453        mat=[mat;mat1];
454    end
455
456endfunction
457
458function Ts=remove_fictitious(Ts,K)
459    //removes fictitious blocks connected links are replaced by a single one
460    //S. Steer, R. Nikoukhah 2003. Copyright INRIA
461    count=min(Ts(:,4))
462    for i=1:size(K,"*")
463        ki=K(i);
464        v1=find(Ts(:,1)==ki);
465        if v1<>[] then
466            v=unique(Ts(v1,4));
467            Ts(v1,:)=[];
468            if size(v)==1 then
469                ind=find(Ts(:,4)==v);
470            else
471                ind = find(dsearch(Ts(:,4),gsort(v,"g","i"),"d")<>0);
472            end
473            if size(ind,"*")>1 then
474                count=count-1;
475                Ts(ind,4)=count
476            else
477                Ts(ind,:)=[]
478            end
479        end
480    end
481endfunction
482
483function cor=update_cor(cor,reg)
484    n=size(cor)
485    for k=1:n
486        if type(cor(k))==15 then
487            cor(k)=update_cor(cor(k),reg)
488        else
489            p=find(cor(k)==reg)
490            if p<>[] then
491                cor(k)=p
492            elseif cor(k)<0 then  // GOTO FROM cases
493                cor(k)=0
494            elseif cor(k)<>0 then
495                cor(k)=size(reg,"*")+1
496            end
497        end
498    end
499endfunction
500