From 47670ad5459f52412f6607c9bb6fc6471d33652f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Sj=C3=B6lund?= Date: Tue, 13 Feb 2018 08:34:27 +0100 Subject: [PATCH] Handle array_get better for multi-dim arrays The code generator can now generate constant indexes for ASUB expressions. The 2D, 3D and 4D-specific array accessors have now been removed (except for String arrays which did not implement these for some reason). --- Compiler/SimCode/SimCodeFunctionUtil.mo | 34 ++++++++++++++++++++++++ Compiler/Template/CodegenCFunctions.tpl | 33 ++++++++++++++++++++--- Compiler/Template/SimCodeTV.mo | 6 ++++- SimulationRuntime/c/util/base_array.h | 4 --- SimulationRuntime/c/util/boolean_array.h | 15 ----------- SimulationRuntime/c/util/integer_array.h | 15 ----------- SimulationRuntime/c/util/real_array.h | 15 ----------- 7 files changed, 68 insertions(+), 54 deletions(-) diff --git a/Compiler/SimCode/SimCodeFunctionUtil.mo b/Compiler/SimCode/SimCodeFunctionUtil.mo index 6068fced0f..eabaf65fc3 100644 --- a/Compiler/SimCode/SimCodeFunctionUtil.mo +++ b/Compiler/SimCode/SimCodeFunctionUtil.mo @@ -2617,6 +2617,40 @@ algorithm outdef := stringDelimitList(List.threadMap(List.fill("i_", nrdims), idxstrlst, stringAppend), ","); end generateSubPalceholders; +public function getConstantSubscriptMemoryLocation "Returns SOME(ix) if the subscript or type is not constant. + For a subscript like [1,4] with dimensions [5,4] it returns 1*4 + 4 to match the C runtime" + input list indexes; + input DAE.Type ty; + output Option outIndex=NONE(); +protected + list dims; + list dimsInt, ixInt; + Integer ndim, sz, ix, i, j; +algorithm + if not Types.dimensionsKnown(ty) then + return; + end if; + dims := Types.getDimensions(ty); + ndim := Types.numberOfDimensions(ty); + if ndim <= 1 or ndim <> listLength(Types.getDimensions(ty)) or ndim <> listLength(indexes) then + return; + end if; + try + dimsInt := listReverse(Expression.dimensionSize(d) for d in dims); + ixInt := listReverse(Expression.expArrayIndex(index) for index in indexes); + ix := 0; + sz := 1; + while not listEmpty(ixInt) loop + i::ixInt := ixInt; + j::dimsInt := dimsInt; + ix := ix + (i-1)*sz; + sz := sz * j; + end while; + outIndex := SOME(ix); + else + end try; +end getConstantSubscriptMemoryLocation; + annotation(__OpenModelica_Interface="backendInterface"); diff --git a/Compiler/Template/CodegenCFunctions.tpl b/Compiler/Template/CodegenCFunctions.tpl index d99e8d64b8..cc40f9ce43 100644 --- a/Compiler/Template/CodegenCFunctions.tpl +++ b/Compiler/Template/CodegenCFunctions.tpl @@ -6314,15 +6314,40 @@ template daeExpAsub(Exp inExp, Context context, Text &preExp, arrayScalarRhs(ecr.ty, subs, arrName, context, &preExp, &varDecls, &auxFunction) case ASUB(exp=e, sub=indexes) then - let exp = daeExp(e, context, &preExp, &varDecls, &auxFunction) let typeShort = expTypeFromExpShort(e) match Expression.typeof(inExp) case T_ARRAY(__) then error(sourceInfo(),'ASUB non-scalar <%ExpressionDumpTpl.dumpExp(inExp,"\"")%>. The inner exp has type: <%unparseType(Expression.typeof(e))%>. After ASUB it is still an array: <%unparseType(Expression.typeof(inExp))%>.') else - let expIndexes = (indexes |> index => '<%daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") - '<%typeShort%>_get<%match listLength(indexes) case 1 then "" case i then '_<%i%>D'%>(<%exp%>, <%expIndexes%>)' - + match getConstantSubscriptMemoryLocation(indexes, Expression.typeof(e)) + case SOME(ix) then + let exp = daeExp(e, context, &preExp, &varDecls, &auxFunction) + '<%typeShort%>_get(<%exp%>, <%ix%>)' + else (match indexes + case {index} then + let exp = daeExp(e, context, &preExp, &varDecls, &auxFunction) + let ix = daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction) + '<%typeShort%>_get(<%exp%>, <%ix%>)' + else + let ix = tempDecl("int", &varDecls) + let sz = tempDecl("int", &varDecls) + let exp = daeExpAsLValue(e, context, &preExp, &varDecls, &auxFunction) + let expIndexes = (indexes |> index => '<%daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction)%>' ;separator=", ") + let tmp = + << + <%ix%> = 0; + <%sz%> = 1; + <% + listReverse(indexes) |> index hasindex i1 fromindex 1 => + << + <%ix%> += <%daeExpASubIndex(index, context, &preExp, &varDecls, &auxFunction)%>; + <%sz%> *= <%exp%>.dim_size[<%intSub(listLength(indexes),i1)%>]; + >> ; separator="\n" + %> + >> + let &preExp += tmp + '<%typeShort%>_get(<%exp%>, /*<%listLength(indexes)%>-dim*/ <%ix%>)' + ) else error(sourceInfo(),'OTHER_ASUB <%ExpressionDumpTpl.dumpExp(inExp,"\"")%>') end daeExpAsub; diff --git a/Compiler/Template/SimCodeTV.mo b/Compiler/Template/SimCodeTV.mo index 073f85f8da..78daafc1be 100644 --- a/Compiler/Template/SimCodeTV.mo +++ b/Compiler/Template/SimCodeTV.mo @@ -1186,7 +1186,11 @@ package SimCodeFunctionUtil output String outdef; end generateSubPalceholders; - + function getConstantSubscriptMemoryLocation + input list indexes; + input DAE.Type ty; + output Option outIndex; + end getConstantSubscriptMemoryLocation; end SimCodeFunctionUtil; diff --git a/SimulationRuntime/c/util/base_array.h b/SimulationRuntime/c/util/base_array.h index 27cec3ff05..a93bd73bb1 100644 --- a/SimulationRuntime/c/util/base_array.h +++ b/SimulationRuntime/c/util/base_array.h @@ -36,10 +36,6 @@ #include #include "omc_msvc.h" -static OMC_INLINE size_t getIndex_2D(_index_t *dim, int i, int j) {return i*dim[1]+j;} -static OMC_INLINE size_t getIndex_3D(_index_t *dim, int i, int j, int k) {return i*dim[1]*dim[2]+j*dim[2]+k;} -static OMC_INLINE size_t getIndex_4D(_index_t *dim, int i, int j, int k, int l) {return i*dim[1]*dim[2]*dim[3]+j*dim[2]*dim[3]+k*dim[3]+l;} - /* Settings the fields of a base_array */ void base_array_create(base_array_t *dest, void *data, int ndims, va_list ap); diff --git a/SimulationRuntime/c/util/boolean_array.h b/SimulationRuntime/c/util/boolean_array.h index 305b4ea129..3b0343cd58 100644 --- a/SimulationRuntime/c/util/boolean_array.h +++ b/SimulationRuntime/c/util/boolean_array.h @@ -42,21 +42,6 @@ static OMC_INLINE modelica_boolean boolean_get(const boolean_array_t a, size_t i return ((modelica_boolean *) a.data)[i]; } -static OMC_INLINE modelica_boolean boolean_get_2D(const boolean_array_t a, size_t i, size_t j) -{ - return boolean_get(a, getIndex_2D(a.dim_size,i,j)); -} - -static OMC_INLINE modelica_boolean boolean_get_3D(const boolean_array_t a, size_t i, size_t j, size_t k) -{ - return boolean_get(a, getIndex_3D(a.dim_size,i,j,k)); -} - -static OMC_INLINE modelica_boolean boolean_get_4D(const boolean_array_t a, size_t i, size_t j, size_t k, size_t l) -{ - return boolean_get(a, getIndex_4D(a.dim_size,i,j,k,l)); -} - /* Setting the fields of a boolean_array */ extern void boolean_array_create(boolean_array_t *dest, modelica_boolean *data, int ndims, ...); diff --git a/SimulationRuntime/c/util/integer_array.h b/SimulationRuntime/c/util/integer_array.h index b30d9234f1..5bb8a22530 100644 --- a/SimulationRuntime/c/util/integer_array.h +++ b/SimulationRuntime/c/util/integer_array.h @@ -43,21 +43,6 @@ static OMC_INLINE modelica_integer integer_get(const integer_array_t a, size_t i return ((modelica_integer *) a.data)[i]; } -static OMC_INLINE modelica_integer integer_get_2D(const integer_array_t a, size_t i, size_t j) -{ - return integer_get(a, getIndex_2D(a.dim_size,i,j)); -} - -static OMC_INLINE modelica_integer integer_get_3D(const integer_array_t a, size_t i, size_t j, size_t k) -{ - return integer_get(a, getIndex_3D(a.dim_size,i,j,k)); -} - -static OMC_INLINE modelica_integer integer_get_4D(const integer_array_t a, size_t i, size_t j, size_t k, size_t l) -{ - return integer_get(a, getIndex_4D(a.dim_size,i,j,k,l)); -} - /* Settings the fields of a integer_array */ extern void integer_array_create(integer_array_t *dest, modelica_integer *data, int ndims, ...); diff --git a/SimulationRuntime/c/util/real_array.h b/SimulationRuntime/c/util/real_array.h index e5a18c8ffe..3e02ed257c 100644 --- a/SimulationRuntime/c/util/real_array.h +++ b/SimulationRuntime/c/util/real_array.h @@ -44,21 +44,6 @@ static OMC_INLINE modelica_real real_get(const real_array_t a, size_t i) return ((modelica_real *) a.data)[i]; } -static OMC_INLINE modelica_real real_get_2D(const real_array_t a, size_t i, size_t j) -{ - return real_get(a, getIndex_2D(a.dim_size,i,j)); -} - -static OMC_INLINE modelica_real real_get_3D(const real_array_t a, size_t i, size_t j, size_t k) -{ - return real_get(a, getIndex_3D(a.dim_size,i,j,k)); -} - -static OMC_INLINE modelica_real real_get_4D(const real_array_t a, size_t i, size_t j, size_t k, size_t l) -{ - return real_get(a, getIndex_4D(a.dim_size,i,j,k,l)); -} - /* Setting the fields of a real_array */ extern void real_array_create(real_array_t *dest, modelica_real *data, int ndims, ...);