mttApplyInterfaceCausality.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. function model = mttApplyInterfaceCausality(model,specified_rule,branch) ;
  2. is_root_model = (nargin==2) ;
  3. objects = mttGetFieldNames(model,'obj') ;
  4. for i = 1:length(objects)
  5. object_name = objects{i} ;
  6. object = getfield(model,'obj',object_name) ;
  7. if isfield(object,'obj')
  8. if is_root_model
  9. branch = object_name ;
  10. else
  11. branch = [branch,'/',object_name] ;
  12. end
  13. object = mttApplyInterfaceCausality(object,specified_rule,branch) ;
  14. model = setfield(model,'obj',object_name,object) ;
  15. else
  16. if ~isempty(object.cr)
  17. if is_root_model
  18. branch = mttDetachText(model.source,'/') ;
  19. end
  20. here = [branch,':',object_name] ;
  21. port_names = mttGetFieldNames(object.cr.interface,'port') ;
  22. for j = 1:length(port_names)
  23. port_name = port_names{j} ;
  24. port = getfield(object.cr.interface,'port',port_name) ;
  25. inbond = port.in ;
  26. outbond = port.out ;
  27. for k = 1:mttGetFieldLength(port,'causality')
  28. rule = port.causality(k).rule ;
  29. definition = port.causality(k).def ;
  30. association = port.causality(k).with ;
  31. not_applied = ~port.causality(k).applied ;
  32. switch rule
  33. case 'assert', is_assertion = 1 ;
  34. case 'prefer', is_assertion = 0 ;
  35. otherwise
  36. error(['Unrecognised rule "',port_causality.rule,'" in ',here]) ;
  37. end
  38. apply_rule = strcmp(specified_rule,rule) & not_applied ;
  39. if apply_rule
  40. switch definition
  41. % case 'effort_state',
  42. % mttAssert(mttIsEqual(port.is_flow_state,0),...
  43. % ['Attempt to overwrite state assignment at port "',port_name,'" in ',here]) ;
  44. % port.is_effort_state = 1 ;
  45. % case 'flow_state',
  46. % mttAssert(mttIsEqual(port.is_effort_state,0),...
  47. % ['Attempt to overwrite state assignment at port "',port_name,'" in ',here]) ;
  48. % port.is_flow_state = 1 ;
  49. case {'effort_in_flow_out','flow_in_effort_out','flow_out_effort_in','effort_out_flow_in'}
  50. mttAssert(isempty(association),...
  51. ['Over-constraint at port "',port_name,'" in ',here]) ;
  52. switch definition
  53. case {'effort_in_flow_out','flow_out_effort_in'},
  54. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,1,1,1) ;
  55. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,0,0,1) ;
  56. case {'flow_in_effort_out','effort_out_flow_in'},
  57. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,0,0,1) ;
  58. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,1,1,1) ;
  59. end
  60. ok = inbond_ok & outbond_ok ;
  61. if is_assertion
  62. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  63. end
  64. case 'effort_in'
  65. mttAssert(isempty(association),...
  66. ['Over-constraint at port "',port_name,'" in ',here]) ;
  67. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,1,[],1) ;
  68. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,0,[],1) ;
  69. ok = inbond_ok & outbond_ok ;
  70. if is_assertion
  71. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  72. end
  73. case 'effort_out'
  74. mttAssert(isempty(association),...
  75. ['Over-constraint at port "',port_name,'" in ',here]) ;
  76. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,0,[],1) ;
  77. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,1,[],1) ;
  78. ok = inbond_ok & outbond_ok ;
  79. if is_assertion
  80. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  81. end
  82. case 'flow_in'
  83. mttAssert(isempty(association),...
  84. ['Over-constraint at port "',port_name,'" in ',here]) ;
  85. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,[],0,1) ;
  86. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,[],1,1) ;
  87. ok = inbond_ok & outbond_ok ;
  88. if is_assertion
  89. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  90. end
  91. case 'flow_out'
  92. mttAssert(isempty(association),...
  93. ['Over-constraint at port "',port_name,'" in ',here]) ;
  94. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,[],1,1) ;
  95. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,[],0,1) ;
  96. ok = inbond_ok & outbond_ok ;
  97. if is_assertion
  98. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  99. end
  100. case 'unicausal',
  101. mttAssert(isempty(association),...
  102. ['Over-constraint at port "',port_name,'" in ',here]) ;
  103. [model,inbond_ok] = mttUpdateBondCausality(model,inbond,[],[],1) ;
  104. [model,outbond_ok] = mttUpdateBondCausality(model,outbond,[],[],1) ;
  105. ok = inbond_ok & outbond_ok ;
  106. if is_assertion
  107. mttAssert(ok,['Causal conflict at port "',port_name,'" in ',here]) ;
  108. end
  109. case {'equicausal','anticausal'}
  110. mttAssert(length(association)==1,...
  111. ['Incorrect constraint at port "',port_name,'" in ',here]) ;
  112. associated_port_name = association{1} ;
  113. associated_port = getfield(cr.interface,'port',associated_port_name) ;
  114. associated_inbond = associated_port.in ;
  115. associated_outbond = associated_port.out ;
  116. mttAsert(xor(isempty(inbond),isempty(outbond)),...
  117. ['Causal rule expects unique bond at port "',port_name,'" in ',here]) ;
  118. mttAsert(xor(isempty(associated_inbond),isempty(associated_outbond)),...
  119. ['Causal rule expects unique bond at port "',associated_port_name,'" in ',here]) ;
  120. if isempty(associated_inbond)
  121. a = associated_outbond ;
  122. else
  123. a = associated_inbond ;
  124. end
  125. if isempty(inbond)
  126. b = outbond ;
  127. else
  128. b = inbond ;
  129. end
  130. switch definition
  131. case 'equicausal',
  132. [model,bond_ok] = mttUpdateBondCausality(model,b,...
  133. model.bond(a).effort,model.bond(a).flow,model.bond(a).unicausal) ;
  134. [model,associated_bond_ok] = mttUpdateBondCausality(model,a,...
  135. model.bond(b).effort,~model.bond(b).flow,model.bond(b).unicausal) ;
  136. case 'anticausal',
  137. [model,bond_ok] = mttUpdateBondCausality(model,b,...
  138. ~model.bond(a).effort,model.bond(a).flow,model.bond(a).unicausal) ;
  139. [model,associated_bond_ok] = mttUpdateBondCausality(model,a,...
  140. ~model.bond(b).effort,~model.bond(b).flow,model.bond(b).unicausal) ;
  141. end
  142. ok = bond_ok & associated_bond_ok ;
  143. if is_assertion
  144. mttAssert(ok,['Causal conflict between ports "',port_name,...
  145. 'and',associated_port_name,'" in ',here]) ;
  146. end
  147. otherwise,
  148. error(['Unrecognised constraint "',definition,'" in ',here]) ;
  149. end
  150. port.causality(k).applied = 1 ;
  151. object = setfield(object,'cr','interface','port',port_name,port) ;
  152. model = setfield(model,'obj',object_name,object) ;
  153. end
  154. end
  155. end
  156. end
  157. end
  158. end