Skip to content

Commit

Permalink
Separate compilation now works with dependency analysis. There are st…
Browse files Browse the repository at this point in the history
…ill some tweaks to be performed though.

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@16788 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Aug 13, 2013
1 parent 170cc45 commit 1215d96
Show file tree
Hide file tree
Showing 10 changed files with 364 additions and 34 deletions.
2 changes: 1 addition & 1 deletion Compiler/FrontEnd/ModelicaBuiltin.mo
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ annotation(Documentation(info="<html><p>Under construction.</p>
end generateSeparateCode;

function generateSeparateCodeDependencies
output String [:,:] dependencies;
output String [:] dependencies;
external "builtin";
annotation(Documentation(info="<html><p>Under construction.</p>
</html>"),preferredView="text");
Expand Down
1 change: 1 addition & 0 deletions Compiler/Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ Flags.mo \
FMI.mo \
Graph.mo \
HashSet.mo \
HashSetString.mo \
HashTable.mo \
HashTable2.mo \
HashTable3.mo \
Expand Down
104 changes: 83 additions & 21 deletions Compiler/Script/CevalScript.mo
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ protected import BackendDAECreate;
protected import BackendDAEUtil;
protected import BackendEquation;
protected import BackendVariable;
protected import BaseHashSet;
protected import Builtin;
protected import CevalFunction;
protected import CheckModel;
Expand All @@ -88,6 +89,7 @@ protected import ExpressionDump;
protected import Flags;
protected import Global;
protected import Graph;
protected import HashSetString;
protected import Inst;
protected import InnerOuter;
protected import List;
Expand Down Expand Up @@ -863,7 +865,7 @@ algorithm
Absyn.ComponentRef crefCName;
list<tuple<String,Values.Value>> resultValues;
list<Real> realVals;
list<tuple<String,list<String>>> deps,depstransitive,depstransposed;
list<tuple<String,list<String>>> deps,depstransitive,depstransposed,depstransposedtransitive,depsmerged,depschanged;
Absyn.CodeNode codeNode;
list<Values.Value> cvars,vals2;
list<Absyn.Path> paths;
Expand All @@ -878,7 +880,8 @@ algorithm
Config.LanguageStandard oldLanguageStd;
SCode.Element cl;
list<SCode.Element> cls;
list<String> names;
list<String> names, namesPublic, namesChanged, fileNames;
HashSetString.HashSet hashSetString;

case (cache,env,"parseString",{Values.STRING(str1),Values.STRING(str2)},st,_)
equation
Expand Down Expand Up @@ -1878,22 +1881,38 @@ algorithm
case (cache,env,"generateSeparateCodeDependencies",{},(st as Interactive.SYMBOLTABLE(ast = p)),_)
equation
sp = SCodeUtil.translateAbsyn2SCode2(p,false);
names = List.map(sp,SCode.getElementName);
names = List.filterMap(sp,SCode.getElementName);

deps = Graph.buildGraph(names,buildDependencyGraph,sp);
depstransitive = Graph.buildGraph(names,buildTransitiveDependencyGraph,deps);
depstransitive = List.sort(depstransitive, compareNumberOfDependencies);
print("Total number of modules: " +& intString(listLength(depstransitive)) +& "\n");
str = stringDelimitList(List.map(depstransitive, transitiveDependencyString), "\n");
print(str +& "\n");
namesPublic = List.map(List.select(sp, containsPublicInterface), SCode.getElementName);
namesChanged = List.filterMap(sp,getChangedClass);
hashSetString = HashSetString.emptyHashSet();
hashSetString = List.fold(namesChanged,BaseHashSet.add,hashSetString);
// print("namesChanged: " +& stringDelimitList(namesChanged, ",") +& "\n");

depstransposed = Graph.transposeGraph(Graph.emptyGraph(names),deps,stringEq);
depstransposed = Graph.buildGraph(names,buildTransitiveDependencyGraph,depstransposed);
depstransposed = List.sort(depstransposed, compareNumberOfDependencies);
// str = stringDelimitList(List.map(depstransposed, dependencyString), "\n");
print("(Transposed) Total number of modules: " +& intString(listLength(depstransposed)) +& "\n");
str = stringDelimitList(List.map(depstransposed, transitiveDependencyString), "\n");
print(str +& "\n");
List.map_0(sp,printInterfaceString);
then (cache,Values.META_FAIL(),st);
depstransposedtransitive = Graph.buildGraph(namesPublic,buildTransitiveDependencyGraph,depstransposed);
// depstransposedtransitive = List.sort(depstransposed, compareNumberOfDependencies);

depstransitive = Graph.transposeGraph(Graph.emptyGraph(names),depstransposedtransitive,stringEq);
depstransitive = List.sort(depstransitive, compareNumberOfDependencies);

depsmerged = Graph.merge(deps,depstransitive,stringEq,compareDependencyNode);
// depsmerged = List.sort(depsmerged, compareNumberOfDependencies);

/*
print("Total number of modules: " +& intString(listLength(depsmerged)) +& "\n");
str = stringDelimitList(List.map(depsmerged, transitiveDependencyString), "\n");
print(str +& "\n");
*/

depschanged = List.select1(depsmerged,isChanged,hashSetString);
names = List.map(depschanged, Util.tuple21);
// print("Files to recompile (" +& intString(listLength(depschanged)) +& "): " +& stringDelimitList(names, ",") +& "\n");
fileNames = List.map1(names, stringAppend, ".c");
_ = List.map(fileNames, System.removeFile);
v = ValuesUtil.makeArray(List.map(names,ValuesUtil.makeString));
then (cache,v,st);

case (cache,env,"generateSeparateCode",{Values.ARRAY(valueLst={})},(st as Interactive.SYMBOLTABLE(ast = p)),_)
equation
Expand Down Expand Up @@ -6922,7 +6941,7 @@ algorithm
edges := matchcontinue (name,oldgraph)
local
String str;
case (_,_) then Graph.allReachableNodes(({name},{}),oldgraph,stringEq);
case (_,_) then List.setDifference(Graph.allReachableNodes(({name},{}),oldgraph,stringEq),{name});
else
equation
str = "CevalScript.buildTransitiveDependencyGraph failed: " +& name;
Expand Down Expand Up @@ -6964,6 +6983,18 @@ algorithm
cmp := listLength(deps1) >= listLength(deps2);
end compareNumberOfDependencies;

protected function compareDependencyNode
input tuple<String,list<String>> node1;
input tuple<String,list<String>> node2;
output Boolean cmp;
protected
String s1,s2;
algorithm
(s1,_) := node1;
(s2,_) := node2;
cmp := Util.strcmpBool(s1,s2);
end compareDependencyNode;

protected function dependencyString
input tuple<String,list<String>> deps;
output String str;
Expand All @@ -6980,8 +7011,8 @@ protected function transitiveDependencyString
protected
list<String> strs;
algorithm
(_,strs) := deps;
str := intString(listLength(strs)) +& ": " +& stringDelimitList(strs, ",");
(str,strs) := deps;
str := intString(listLength(strs)) +& ": ("+&str+&") " +& stringDelimitList(strs, ",");
end transitiveDependencyString;

protected function containsPublicInterface
Expand Down Expand Up @@ -7013,11 +7044,11 @@ algorithm
case SCode.CLASS(restriction=SCode.R_FUNCTION(_)) then false;
case SCode.COMPONENT(name=name,prefixes=SCode.PREFIXES(visibility=SCode.PUBLIC()))
equation
print("public component " +& name +& ": ");
// print("public component " +& name +& ": ");
then true;
case SCode.CLASS(name=name,prefixes=SCode.PREFIXES(visibility=SCode.PUBLIC()))
equation
print("public class " +& name +& ": ");
// print("public class " +& name +& ": ");
then true;
else false;
end match;
Expand All @@ -7032,4 +7063,35 @@ algorithm
print(str +& ": " +& boolString(containsPublicInterface(elt)) +& "\n");
end printInterfaceString;

protected function getChangedClass
input SCode.Element elt;
output String name;
algorithm
name := matchcontinue elt
local
String fileName;
case SCode.CLASS(name=name,info=Absyn.INFO(fileName=fileName))
equation
false = System.regularFileExists(name +& ".c");
then name;
case SCode.CLASS(name=name,info=Absyn.INFO(fileName=fileName))
equation
true = System.fileIsNewerThan(fileName, name +& ".c");
then name;
end matchcontinue;
end getChangedClass;

protected function isChanged
input tuple<String,list<String>> node;
input HashSetString.HashSet hs;
output Boolean b;
protected
String str;
list<String> strs;
algorithm
(str,strs) := node;
b := List.exist1(str::strs,BaseHashSet.has,hs);
// print(str +& ": " +& boolString(b) +& "\n");
end isChanged;

end CevalScript;
74 changes: 74 additions & 0 deletions Compiler/Util/Graph.mo
Original file line number Diff line number Diff line change
Expand Up @@ -1117,4 +1117,78 @@ algorithm
end matchcontinue;
end filterGraph2;

public function merge "Merges the nodes of two different graphs. Needs an ordering function in order to be efficient."
input list<tuple<NodeType, list<NodeType>>> graph1;
input list<tuple<NodeType, list<NodeType>>> graph2;
input EqualFunc eqFunc;
input CompareFunc compareFunc;
output list<tuple<NodeType, list<NodeType>>> graph;
partial function EqualFunc
"Given two nodes, returns true if they are equal, otherwise false."
input NodeType inNode1;
input NodeType inNode2;
output Boolean isEqual;
end EqualFunc;
partial function CompareFunc
"Given two nodes, returns true if the first is ordered before the second."
input tuple<NodeType,list<NodeType>> inNode1;
input tuple<NodeType,list<NodeType>> inNode2;
output Boolean isEqual;
end CompareFunc;
algorithm
graph := merge2(List.sort(listAppend(graph1,graph2), compareFunc), eqFunc, {});
end merge;

protected function merge2
input list<tuple<NodeType, list<NodeType>>> inGraph;
input EqualFunc eqFunc;
input list<tuple<NodeType, list<NodeType>>> inAcc;
output list<tuple<NodeType, list<NodeType>>> graph;
partial function EqualFunc
"Given two nodes, returns true if they are equal, otherwise false."
input NodeType inNode1;
input NodeType inNode2;
output Boolean isEqual;
end EqualFunc;
algorithm
graph := match (inGraph,eqFunc,inAcc)
local
list<tuple<NodeType, list<NodeType>>> rest;
tuple<NodeType, list<NodeType>> node;
NodeType n1,n2;
list<NodeType> e1,e2;
Boolean b;
case ({},_,_) then listReverse(inAcc);
case ({node},_,_) then listReverse(node::inAcc);
case ((n1,e1)::(n2,e2)::rest,_,_)
equation
b = eqFunc(n1,n2);
(node,rest) = merge3(b,n1,e1,n2,e2,rest,eqFunc);
then merge2(rest,eqFunc,node::inAcc);
end match;
end merge2;

protected function merge3
input Boolean b;
input NodeType n1;
input list<NodeType> e1;
input NodeType n2;
input list<NodeType> e2;
input list<tuple<NodeType, list<NodeType>>> rest;
input EqualFunc eqFunc;
output tuple<NodeType, list<NodeType>> elt;
output list<tuple<NodeType, list<NodeType>>> outRest;
partial function EqualFunc
"Given two nodes, returns true if they are equal, otherwise false."
input NodeType inNode1;
input NodeType inNode2;
output Boolean isEqual;
end EqualFunc;
algorithm
(elt,outRest) := match (b,n1,e1,n2,e2,rest,eqFunc)
case (true,_,_,_,_,_,_) then ((n1,List.unionOnTrue(e1,e2,eqFunc)),rest);
case (false,_,_,_,_,_,_) then ((n1,e1),(n2,e2)::rest);
end match;
end merge3;

end Graph;
94 changes: 94 additions & 0 deletions Compiler/Util/HashSetString.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-CurrentYear, Linköping University,
* Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3
* AND THIS OSMC PUBLIC LICENSE (OSMC-PL).
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
* ACCEPTANCE OF THE OSMC PUBLIC LICENSE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from Linköping University, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS
* OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/

encapsulated package HashSetString "HashSet of strings."

/* Below is the instance specific code. For each hashset the user must define:
Key - The key used to uniquely define elements in a hashset
hashFunc - A function that maps a key to a positive integer.
keyEqual - A comparison function between two keys, returns true if equal.
*/

/* HashSet instance specific code */

public import BaseHashSet;
protected import System;
protected import Util;

public type Key = String;

public type HashSetCrefFunctionsType = tuple<FuncHashCref,FuncCrefEqual,FuncCrefStr>;
public type HashSet = tuple<
array<list<tuple<Key,Integer>>>,
tuple<Integer,Integer,array<Option<Key>>>,
Integer,
Integer,
HashSetCrefFunctionsType
>;

partial function FuncHashCref
input Key cr;
input Integer mod;
output Integer res;
end FuncHashCref;

partial function FuncCrefEqual
input Key cr1;
input Key cr2;
output Boolean res;
end FuncCrefEqual;

partial function FuncCrefStr
input Key cr;
output String res;
end FuncCrefStr;

public function emptyHashSet
"
Returns an empty HashSet.
Using the default bucketsize..
"
output HashSet hashSet;
algorithm
hashSet := emptyHashSetSized(BaseHashSet.defaultBucketSize);
end emptyHashSet;

public function emptyHashSetSized
"Returns an empty HashSet.
Using the bucketsize size"
input Integer size;
output HashSet hashSet;
algorithm
hashSet := BaseHashSet.emptyHashSetWork(size,(System.stringHashDjb2Mod,stringEq,Util.id));
end emptyHashSetSized;

end HashSetString;

0 comments on commit 1215d96

Please sign in to comment.