Skip to content

Commit dbfaced

Browse files
authored
Improve recreation of records in simulation context. (#10091)
- When re-creating a record from its member variables in simulation code (to send to a function), we were using the Modelica record constructor function created for it automatically. This requires considering which members are marked as protected and are considered non-modifiable. While this can be done it requires more analysis at codegen time to figure out. Instead, always recreate a record using all its members (for this specific purpose of sending to a function). This is cleaner and also more error proof because it leaves no chance for overlooking any member being protected but getting modified by some other mechanism. - A new record utility function, `<rec_name>_wrap_from_vars` is now added for each record. This simple function will **assign** the members of a record from the function parameters. The function expects all members of the record as input. **Note that the function does not do any deep copy** of the record members from the function parameters. It just assigns them. This might not be the ideal thing to do but it is necessary right now due to the fact that a record can have an array member variable whose size is dictated by another record member variable. This means a give instance of a record might not be exactly compatible with the declaration due to array size differences, i.e., not copyable to a default allocated record. The solution to this issue is probably in the NF (if it can be done). The NF should mark these size modified records as new pseudo-types so CodeGen can differentiate them. Fixes #10084.
1 parent 2063a00 commit dbfaced

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

OMCompiler/Compiler/Template/CodegenCFunctions.tpl

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ template recordDeclaration(RecordDeclaration recDecl)
428428
listLength(variables))%>
429429

430430
<%recordConstructorDef(r.name, r.name, r.variables)%>
431-
<%recordModelicaCallConstrctor(r.name, r.variables)%>
431+
<%recordCreateFromVarsDef(r.name, r.variables)%>
432432

433433
<%recordCopyDef(r.name, r.variables)%>
434434
<%if r.usedExternally then recordCopyExternalDefs(r.name, r.variables)%>
@@ -532,8 +532,10 @@ template recordDeclarationFullHeader(RecordDeclaration recDecl)
532532
let copy_to_vars_name_p = '<%copy_to_vars_name%>_p'
533533
let copy_to_vars_inputs = r.variables |> var as VARIABLE(__) => (", " + varType(var) + "* in_" + crefStr(var.name))
534534

535-
let modelica_ctor_name = 'omc_<%rec_name%>'
536-
let modelica_ctor_inputs = r.variables |> var as VARIABLE(__) => (", " + varType(var) + " in_" + crefStr(var.name))
535+
let wrap_vars_macro_name = '<%rec_name%>_wrap_vars'
536+
let wrap_vars_func_name = '<%wrap_vars_macro_name%>_p'
537+
let wrap_vars_macro_inputs = r.variables |> var as VARIABLE(__) => (", " + "in_" + crefStr(var.name))
538+
let wrap_vars_func_inputs = r.variables |> var as VARIABLE(__) => (", " + varType(var) + " in_" + crefStr(var.name))
537539

538540
<<
539541
<% match aliasName
@@ -575,9 +577,9 @@ template recordDeclarationFullHeader(RecordDeclaration recDecl)
575577
#define <%cpy_from_external_macro_name%>(src,dst) <%cpy_from_external_func_name%>(&src, &dst)
576578
>>
577579
%>
578-
// This function should eventually replace the default 'modelica' record constructor funcition
579-
// that omc used to generate, i.e., replace functionBodyRecordConstructor template.
580-
// <%rec_name%> <%modelica_ctor_name%>(threadData_t *threadData <%modelica_ctor_inputs%>);
580+
581+
void <%wrap_vars_func_name%>(threadData_t *threadData , void* v_dst <%wrap_vars_func_inputs%>);
582+
#define <%wrap_vars_macro_name%>(td, dst <%wrap_vars_macro_inputs%>) <%wrap_vars_func_name%>(td, &dst <%wrap_vars_macro_inputs%>)
581583

582584
// This function is not needed anymore. If you want to know how a record
583585
// is 'assigned to' in simulation context see assignRhsExpToRecordCrefSimContext and
@@ -644,50 +646,43 @@ template recordCopyExternalDefs(String rec_name, list<Variable> variables)
644646
>>
645647
end recordCopyExternalDefs;
646648

647-
template recordModelicaCallConstrctor(String rec_name, list<Variable> variables)
648-
"Generates code for creating and initializing a record given values for
649-
ALL its members. This is basically what we used to generate before. However
650-
that one did not handle arrays and record record members properly. This
651-
should replace that function. For now it is commented until I have time to
652-
clean out uses of the other one and replace it with this.
653-
654-
Note that this is defferent from the constructors we have. This is the function
655-
to be used when you do R(...). not for cases where you have
656-
657-
R r1; (uses default constructor, i e., recordDeclarationFullHeader and recordConstructorDef)
658-
R r2(a=2); (uses extra constructor, i e., recordDeclarationExtraCtor and recordConstructorDef)
659-
...
660-
661-
But for cases like these.
662-
a := R() (should use this function)
649+
template recordCreateFromVarsDef(String rec_name, list<Variable> variables)
650+
"Generates code for creating and initializing (shallow copies) a record given values for
651+
ALL its members. This is used internally by the generated code to reconstruct
652+
records from (the scattered) simulation member variables of the record. We do
653+
this when we have to send a record used in equation context to a function.
663654

664-
The difference is this function creates and returns a NEW record instance. The others
665-
accept an instance and initialize it (including any allocations needed by the MEMBERS).
655+
Note that this is defferent from the constructors we have. This one expects
656+
all the memebers to be already created (allocated and given values whatever the value is).
657+
Its job is to 'wrap' these variables by a given record instance, e.g., so it can be sent to
658+
functions from simulation code.
666659
"
667660
::=
668-
let &varCopies = buffer ""
669661
let &auxFunction = buffer ""
670-
let dst_pref = 'dst.'
671-
let src_pref = ' in'
672-
let _ = (variables |> var => recordMemberCopy(var, src_pref, dst_pref, &varCopies, &auxFunction) ;separator="\n")
673-
let inputs = (variables |> var as VARIABLE(__) =>
662+
let dst_pref = 'dst->'
663+
let src_pref = 'in'
664+
665+
let varCopies = (variables |> var => match var
666+
case var as VARIABLE(__) then
667+
let dstName = dst_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
668+
let srcName = src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction)
669+
'<%dstName%> = <%srcName%>;<%\n%>'
670+
else error(sourceInfo(), "recordCreateFromVarsDef: Unhandled variable type"))
671+
672+
let fn_inputs = (variables |> var as VARIABLE(__) =>
674673
(", " + varType(var) + " " + src_pref + contextCrefNoPrevExp(var.name, contextFunction, &auxFunction))
675674
)
675+
676+
let ctor_additional_inputs = (variables |> var as VARIABLE(__) => if var.bind_from_outside
677+
then (", " + "in_" + crefStr(var.name))
678+
)
676679
<<
677-
// This function should eventually replace the default 'modelica' record constructor funcition
678-
// that omc used to generate, i.e., replace functionBodyRecordConstructor template.
679-
/*
680-
<%rec_name%> omc_<%rec_name%>(threadData_t *threadData <%inputs%>) {
681-
<%rec_name%> dst;
682-
// TODO Improve me. No need to initialize the record members with defaults in <%rec_name%>_construct
683-
// We should just do the allocs here and then copy the input parameters as default values instead.
684-
<%rec_name%>_construct(threadData, dst);
680+
void <%rec_name%>_wrap_vars_p(threadData_t *threadData, void* v_dst <%fn_inputs%>) {
681+
<%rec_name%>* dst = (<%rec_name%>*)(v_dst);
685682
<%varCopies%>
686-
return dst;
687683
}
688-
*/
689684
>>
690-
end recordModelicaCallConstrctor;
685+
end recordCreateFromVarsDef;
691686

692687
template recordMemberCopy(Variable var, String src_pref, String dst_pref, Text &varCopies, Text &auxFunction)
693688
"Generates code for copying memembers of a record during a record copy operation.
@@ -5395,7 +5390,9 @@ template daeExpCrefRhsSimContext(Exp ecr, Context context, Text &preExp,
53955390
case ecr as CREF(componentRef = cr, ty = t as T_COMPLEX(complexClassType = record_state, varLst = var_lst)) then
53965391
let vars = var_lst |> v => (", " + constVarOrDaeExp(v, cr, context, &preExp, &varDecls, &auxFunction))
53975392
let record_type_name = underscorePath(ClassInf.getStateName(record_state))
5398-
'omc_<%record_type_name%>(threadData<%vars%>)'
5393+
let tmpRec = tempDecl(record_type_name, &varDecls)
5394+
let &preExp += '<%record_type_name%>_wrap_vars(threadData,<%tmpRec%><%vars%>);<%\n%>'
5395+
'<%tmpRec%>'
53995396

54005397
case ecr as CREF(componentRef=cr, ty=T_ARRAY(ty=aty, dims=dims)) then
54015398
let type = expTypeShort(aty)

0 commit comments

Comments
 (0)