Module openrtdynamics2.lang.code_generation_templates

Expand source code
from .diagram_core.code_build_commands import *
from .diagram_core.system_manifest import *
from .diagram_core import diagram_compiler
from .libraries import *

import subprocess
import os
import json
from pathlib import Path


def _generate_algorithm_code( compile_results, enable_tracing=False, included_systems={}, include_code_list : List[str] = [] ):
    """
        generate code for the given compile result

        compile_results    - the compilation results of the a system
        enable_tracing     - include debuging
        included_systems   - unused so far
        include_code_list  - list of strings containing code to include
    """

    main_command = compile_results.command_to_execute

    algorithm_code = ''

    # enable tracing for all execution commands
    if enable_tracing:
        # TODO: instead of putting True create an obj with a tracing infrastructure. So far printf is used automatically
        main_command.command_to_put_main_system.set_tracing_infrastructure(True)

    # concatenate the custom code to include
    if include_code_list is not None:
        for code in include_code_list:
            algorithm_code += '// custom code\n' + code + '\n// end of custom code\n\n'

    # combine (concatenate) the code from the library entries
    for include in included_systems:
        algorithm_code += include.sourceCode

    # build the code for the implementation
    main_command.generate_code_init('c++')
    algorithm_code += main_command.generate_code('c++', 'code')
    main_command.generate_code_destruct('c++')

    # the manifest containts meta-information about the simulation and its interface
    # i.e. input and output signals names and datatypes
    manifest = compile_results.manifest.export_json()

    return manifest, algorithm_code




class TargetGenericCpp:
    """
        generates code for the runtime environment
    """

    def __init__(self, enable_tracing=False ):
        ExecutionCommand.__init__(self)  # TODO: what is this?

        # if compile_results is not None:
        #     self.compileResults = compile_results
        #     self.main_command = compile_results.command_to_execute

        # else:

        # those are set via set_compile_results after a system is compiled
        self.compileResults = None
        self.main_command = None
        self._include_code_list = None

        #
        self._algorithm_code = None

        # list of systems to include
        self._includedSystems = []

        self._enable_tracing = enable_tracing

    def set_compile_results(self, compile_results : CompileResults ):
        self.compileResults = compile_results
        self.main_command = compile_results.command_to_execute

    def include_systems(self, system : SystemLibraryEntry):
        self._includedSystems = system

    def add_code_to_include(self, include_code_list : List[str] = []):
        self._include_code_list = include_code_list

    def get_algorithm_code(self):
        """
            Return only the code that implement the system and all sub systems
        """
        return self._algorithm_code



    def code_gen(self):

        # generate code for the algorithm
        self.manifest, self._algorithm_code = _generate_algorithm_code(
            self.compileResults, 
            self._enable_tracing, 
            self._includedSystems, 
            self._include_code_list
        )

        
        # TODO: iterate over all functions present in the API of the system
        # NOTE: Currently only the main functions are used: output, update, and reset
        #
        API_functions = self.main_command.command_to_put_main_system.API_functions

        #
        # make strings 
        # 

        def makeStrings(signals):
            names_CSV_list = cgh.signal_list_to_names_string(signals)
            names_var_def = cgh.define_variable_list_string(signals)
            printf_pattern = cgh.signalListHelper_printfPattern_string(signals)

            return names_CSV_list, names_var_def, printf_pattern


        # for the output signals
        # input1_NamesCSVList; list of output signals. e.g. 'y1, y2, y3' 
        outputNamesCSVList, outputNamesVarDef, outputPrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.outputSignals )

        # the inputs to the output command
        # input1_NamesCSVList: list of output signals. e.g. 'y1, y2, y3' 
        input1_NamesCSVList, input1_NamesVarDef, input1PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.inputSignals )

        # the inputs to the update command
        # input2_NamesCSVList list of output signals. e.g. 'u1, u2, u3' 
        input2_NamesCSVList, input2_NamesVarDef, input2_PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.updateCommand.inputSignals )

        # all inputs
        # merge the list of inputs for the calcoutput and stateupdate function
        allInputs = list(set(self.main_command.command_to_put_main_system.outputCommand.inputSignals + self.main_command.command_to_put_main_system.updateCommand.inputSignals))
        inputAll_NamesCSVList, inputAll_NamesVarDef, inputAll_PrinfPattern = makeStrings( allInputs )

        # the names of input and output signals of the outputCommand combined
        calcOutputsArgs = cgh.signal_list_to_name_list( self.main_command.command_to_put_main_system.outputCommand.outputSignals + self.main_command.command_to_put_main_system.outputCommand.inputSignals )

        # fill in template
        self.template = Template(self.template).safe_substitute(  
                                                    mainSimulationName = self.main_command.command_to_put_main_system.API_name,
                                                    algorithmCode=self._algorithm_code,

                                                    input1_NamesVarDef=input1_NamesVarDef,
                                                    input1_NamesCSVList=input1_NamesCSVList,

                                                    input2_NamesVarDef=input2_NamesVarDef,
                                                    input2_NamesCSVList=input2_NamesCSVList,

                                                    inputAll_NamesVarDef=inputAll_NamesVarDef,
                                                    inputAll_NamesCSVList=inputAll_NamesCSVList,

                                                    outputNamesCSVList=outputNamesCSVList, 
                                                    outputNamesVarDef=outputNamesVarDef,
                                                    outputPrinfPattern=outputPrinfPattern,
                                                    
                                                    calcOutputsArgs=calcOutputsArgs )


        return {'sourcecode' : self.template, 'manifest' : self.manifest, 'algorithm_sourcecode' : self._algorithm_code }

    def writeFiles(self, folder):

        with open( os.path.join( folder + '//simulation_manifest.json' ), 'w') as outfile:  
            json.dump(self.manifest, outfile)

    def build(self):
        pass

    def run(self):
        pass




class TargetBasicExecutable(TargetGenericCpp):
    """
        generates code for the runtime environment
    """

    def __init__(self, i_max : int, input_signals_mapping = {} ):

        self._i_max = i_max

        TargetGenericCpp.__init__(self)

        self.input_signals_mapping = input_signals_mapping
        self.initCodeTemplate()

        
    def code_gen(self):

        # call helper to fill in some generic elements into the template
        code_gen_results = TargetGenericCpp.code_gen(self)

        #
        # make strings 
        # 

        # constant inputs
        inputConstAssignments = []
        for signal, value in self.input_signals_mapping.items():
            inputConstAssignments.append( signal.name + ' = ' + str(value) )

        inputConstAssignment = '; '.join( inputConstAssignments ) + ';'

        self.sourceCode = Template(self.template).safe_substitute( iMax=self._i_max,
                                                                 inputConstAssignment=inputConstAssignment    ) 

        code_gen_results['sourcecode'] = self.sourceCode
        return code_gen_results

    def write_code(self, folder):
        TargetGenericCpp.writeFiles(self, folder)

        self.codeFolder = folder

        f = open(os.path.join( folder + "main.cpp"), "w")
        f.write( self.sourceCode )
        f.close()


    def build(self):
        os.system("c++ " + self.codeFolder + "main.cpp -o " + self.codeFolder + "main")


    def run(self):
        # run the generated executable
        p = subprocess.Popen(self.codeFolder + 'main', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        retval = p.wait()

        # parse csv data
        data = [ ]
        outputs = range(0, len(self.main_command.command_to_put_main_system.outputCommand.outputSignals) )

        for o in outputs:
            data.append( [] )

        for line in p.stdout.readlines():
            sample = line.decode("utf-8").split(' ')

            for o in outputs:
                data[ o ].append( float( sample[o] ) )

        # put data into a key-array
        dataStruct = { }
        o = 0
        for s in self.main_command.command_to_put_main_system.outputCommand.outputSignals:
            dataStruct[ s.name ] = data[o]

            o = o + 1

        return dataStruct


    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>

//
// implementation of $mainSimulationName
//

$algorithmCode

//
// main
//

int main () {

    // create an instance of the simulation
    $mainSimulationName simulation;

    // input signals
    $inputAll_NamesVarDef

    // output signals
    $outputNamesVarDef

    // const assignments of the input signals
    $inputConstAssignment

    // reset the simulation
    simulation.resetStates();

    // simulate
    int i;

    for (i=0; i< $iMax; ++i) {
        simulation.calcResults_1( $calcOutputsArgs );
        simulation.updateStates(  $input2_NamesCSVList );

        printf("$outputPrinfPattern\\n", $outputNamesCSVList);
    }

}

            
        """        








class TargetWasm(TargetGenericCpp):
    """
        generates code for the Webassemble runtime environment

        https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html

    """

    def __init__(self, enable_tracing = False ):

        TargetGenericCpp.__init__(self, enable_tracing=enable_tracing)

        self.initCodeTemplate()

        
    def code_gen(self):

        # build I/O structs
        ioExport = self.generate_code_writeIO(self.main_command.command_to_put_main_system.outputCommand)
        ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.updateCommand)

        ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.resetCommand)

        self.template = Template(self.template).safe_substitute( ioExport=ioExport,
                                                                 inputConstAssignment=''    ) 

        # call helper to fill in some generic elements into the template
        code_gen_results = TargetGenericCpp.code_gen(self)

        self.sourceCode = self.template

        code_gen_results['sourcecode'] = self.sourceCode
        return code_gen_results



    def generate_code_writeIO__(self, command_API, inputOutput : int):

        if inputOutput == 1:
            structPrefix = 'Inputs_'
            signals = command_API.inputSignals

        elif inputOutput == 2:
            structPrefix = 'Outputs_'
            signals = command_API.outputSignals

        mainSimulationName = self.main_command.command_to_put_main_system.API_name

        lines = ''

        # Inputs
        structname = structPrefix + command_API.API_name 

        lines += 'value_object<' + mainSimulationName + '::' + structname + '>("' + mainSimulationName + '__' + structname + '")\n'

        for s in signals:
            fieldName = s.name

            lines += '.field("' + fieldName + '", &' + mainSimulationName + '::' + structname + '::' + fieldName + ')\n'

        lines += ';\n\n'


        return lines

    def generate_code_writeIO(self, command_API):
        return self.generate_code_writeIO__(command_API, 1) + self.generate_code_writeIO__(command_API, 2)


    def write_code(self, folder):

        TargetGenericCpp.writeFiles(self, folder)

        self.codeFolder = folder

        f = open( Path( folder ) / "main.cpp", "w")
        f.write( self.sourceCode )
        f.close()


    def build(self):

        buildCommand = 'emcc --bind -s MODULARIZE=1 -s EXPORT_NAME="ORTD_simulator" '  + os.path.join(self.codeFolder , "main.cpp") + " -g4 -s -o " + os.path.join( self.codeFolder , "main.js" )
        print("Running compiler: " + buildCommand)

        returnCode = os.system(buildCommand)

        print( "Compilation result: ", returnCode )


    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>
#include <emscripten/bind.h>

using namespace emscripten;

//
// implementation of $mainSimulationName
//

$algorithmCode

// Binding code
EMSCRIPTEN_BINDINGS(my_class_example) {
  class_<$mainSimulationName>("$mainSimulationName")
    .constructor<>()
    .function("resetStates", &$mainSimulationName::resetStates__)
    .function("calcResults_1", &$mainSimulationName::calcResults_1__)
    .function("updateStates", &$mainSimulationName::updateStates__)
    ;


// --------------------------------

$ioExport


}
            
        """        

Classes

class TargetBasicExecutable (i_max: int, input_signals_mapping={})

generates code for the runtime environment

Expand source code
class TargetBasicExecutable(TargetGenericCpp):
    """
        generates code for the runtime environment
    """

    def __init__(self, i_max : int, input_signals_mapping = {} ):

        self._i_max = i_max

        TargetGenericCpp.__init__(self)

        self.input_signals_mapping = input_signals_mapping
        self.initCodeTemplate()

        
    def code_gen(self):

        # call helper to fill in some generic elements into the template
        code_gen_results = TargetGenericCpp.code_gen(self)

        #
        # make strings 
        # 

        # constant inputs
        inputConstAssignments = []
        for signal, value in self.input_signals_mapping.items():
            inputConstAssignments.append( signal.name + ' = ' + str(value) )

        inputConstAssignment = '; '.join( inputConstAssignments ) + ';'

        self.sourceCode = Template(self.template).safe_substitute( iMax=self._i_max,
                                                                 inputConstAssignment=inputConstAssignment    ) 

        code_gen_results['sourcecode'] = self.sourceCode
        return code_gen_results

    def write_code(self, folder):
        TargetGenericCpp.writeFiles(self, folder)

        self.codeFolder = folder

        f = open(os.path.join( folder + "main.cpp"), "w")
        f.write( self.sourceCode )
        f.close()


    def build(self):
        os.system("c++ " + self.codeFolder + "main.cpp -o " + self.codeFolder + "main")


    def run(self):
        # run the generated executable
        p = subprocess.Popen(self.codeFolder + 'main', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        retval = p.wait()

        # parse csv data
        data = [ ]
        outputs = range(0, len(self.main_command.command_to_put_main_system.outputCommand.outputSignals) )

        for o in outputs:
            data.append( [] )

        for line in p.stdout.readlines():
            sample = line.decode("utf-8").split(' ')

            for o in outputs:
                data[ o ].append( float( sample[o] ) )

        # put data into a key-array
        dataStruct = { }
        o = 0
        for s in self.main_command.command_to_put_main_system.outputCommand.outputSignals:
            dataStruct[ s.name ] = data[o]

            o = o + 1

        return dataStruct


    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>

//
// implementation of $mainSimulationName
//

$algorithmCode

//
// main
//

int main () {

    // create an instance of the simulation
    $mainSimulationName simulation;

    // input signals
    $inputAll_NamesVarDef

    // output signals
    $outputNamesVarDef

    // const assignments of the input signals
    $inputConstAssignment

    // reset the simulation
    simulation.resetStates();

    // simulate
    int i;

    for (i=0; i< $iMax; ++i) {
        simulation.calcResults_1( $calcOutputsArgs );
        simulation.updateStates(  $input2_NamesCSVList );

        printf("$outputPrinfPattern\\n", $outputNamesCSVList);
    }

}

            
        """        

Ancestors

Methods

def build(self)
Expand source code
def build(self):
    os.system("c++ " + self.codeFolder + "main.cpp -o " + self.codeFolder + "main")
def code_gen(self)
Expand source code
def code_gen(self):

    # call helper to fill in some generic elements into the template
    code_gen_results = TargetGenericCpp.code_gen(self)

    #
    # make strings 
    # 

    # constant inputs
    inputConstAssignments = []
    for signal, value in self.input_signals_mapping.items():
        inputConstAssignments.append( signal.name + ' = ' + str(value) )

    inputConstAssignment = '; '.join( inputConstAssignments ) + ';'

    self.sourceCode = Template(self.template).safe_substitute( iMax=self._i_max,
                                                             inputConstAssignment=inputConstAssignment    ) 

    code_gen_results['sourcecode'] = self.sourceCode
    return code_gen_results
def initCodeTemplate(self)
Expand source code
    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>

//
// implementation of $mainSimulationName
//

$algorithmCode

//
// main
//

int main () {

    // create an instance of the simulation
    $mainSimulationName simulation;

    // input signals
    $inputAll_NamesVarDef

    // output signals
    $outputNamesVarDef

    // const assignments of the input signals
    $inputConstAssignment

    // reset the simulation
    simulation.resetStates();

    // simulate
    int i;

    for (i=0; i< $iMax; ++i) {
        simulation.calcResults_1( $calcOutputsArgs );
        simulation.updateStates(  $input2_NamesCSVList );

        printf("$outputPrinfPattern\\n", $outputNamesCSVList);
    }

}

            
        """        
def run(self)
Expand source code
def run(self):
    # run the generated executable
    p = subprocess.Popen(self.codeFolder + 'main', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    retval = p.wait()

    # parse csv data
    data = [ ]
    outputs = range(0, len(self.main_command.command_to_put_main_system.outputCommand.outputSignals) )

    for o in outputs:
        data.append( [] )

    for line in p.stdout.readlines():
        sample = line.decode("utf-8").split(' ')

        for o in outputs:
            data[ o ].append( float( sample[o] ) )

    # put data into a key-array
    dataStruct = { }
    o = 0
    for s in self.main_command.command_to_put_main_system.outputCommand.outputSignals:
        dataStruct[ s.name ] = data[o]

        o = o + 1

    return dataStruct
def write_code(self, folder)
Expand source code
def write_code(self, folder):
    TargetGenericCpp.writeFiles(self, folder)

    self.codeFolder = folder

    f = open(os.path.join( folder + "main.cpp"), "w")
    f.write( self.sourceCode )
    f.close()

Inherited members

class TargetGenericCpp (enable_tracing=False)

generates code for the runtime environment

Expand source code
class TargetGenericCpp:
    """
        generates code for the runtime environment
    """

    def __init__(self, enable_tracing=False ):
        ExecutionCommand.__init__(self)  # TODO: what is this?

        # if compile_results is not None:
        #     self.compileResults = compile_results
        #     self.main_command = compile_results.command_to_execute

        # else:

        # those are set via set_compile_results after a system is compiled
        self.compileResults = None
        self.main_command = None
        self._include_code_list = None

        #
        self._algorithm_code = None

        # list of systems to include
        self._includedSystems = []

        self._enable_tracing = enable_tracing

    def set_compile_results(self, compile_results : CompileResults ):
        self.compileResults = compile_results
        self.main_command = compile_results.command_to_execute

    def include_systems(self, system : SystemLibraryEntry):
        self._includedSystems = system

    def add_code_to_include(self, include_code_list : List[str] = []):
        self._include_code_list = include_code_list

    def get_algorithm_code(self):
        """
            Return only the code that implement the system and all sub systems
        """
        return self._algorithm_code



    def code_gen(self):

        # generate code for the algorithm
        self.manifest, self._algorithm_code = _generate_algorithm_code(
            self.compileResults, 
            self._enable_tracing, 
            self._includedSystems, 
            self._include_code_list
        )

        
        # TODO: iterate over all functions present in the API of the system
        # NOTE: Currently only the main functions are used: output, update, and reset
        #
        API_functions = self.main_command.command_to_put_main_system.API_functions

        #
        # make strings 
        # 

        def makeStrings(signals):
            names_CSV_list = cgh.signal_list_to_names_string(signals)
            names_var_def = cgh.define_variable_list_string(signals)
            printf_pattern = cgh.signalListHelper_printfPattern_string(signals)

            return names_CSV_list, names_var_def, printf_pattern


        # for the output signals
        # input1_NamesCSVList; list of output signals. e.g. 'y1, y2, y3' 
        outputNamesCSVList, outputNamesVarDef, outputPrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.outputSignals )

        # the inputs to the output command
        # input1_NamesCSVList: list of output signals. e.g. 'y1, y2, y3' 
        input1_NamesCSVList, input1_NamesVarDef, input1PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.inputSignals )

        # the inputs to the update command
        # input2_NamesCSVList list of output signals. e.g. 'u1, u2, u3' 
        input2_NamesCSVList, input2_NamesVarDef, input2_PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.updateCommand.inputSignals )

        # all inputs
        # merge the list of inputs for the calcoutput and stateupdate function
        allInputs = list(set(self.main_command.command_to_put_main_system.outputCommand.inputSignals + self.main_command.command_to_put_main_system.updateCommand.inputSignals))
        inputAll_NamesCSVList, inputAll_NamesVarDef, inputAll_PrinfPattern = makeStrings( allInputs )

        # the names of input and output signals of the outputCommand combined
        calcOutputsArgs = cgh.signal_list_to_name_list( self.main_command.command_to_put_main_system.outputCommand.outputSignals + self.main_command.command_to_put_main_system.outputCommand.inputSignals )

        # fill in template
        self.template = Template(self.template).safe_substitute(  
                                                    mainSimulationName = self.main_command.command_to_put_main_system.API_name,
                                                    algorithmCode=self._algorithm_code,

                                                    input1_NamesVarDef=input1_NamesVarDef,
                                                    input1_NamesCSVList=input1_NamesCSVList,

                                                    input2_NamesVarDef=input2_NamesVarDef,
                                                    input2_NamesCSVList=input2_NamesCSVList,

                                                    inputAll_NamesVarDef=inputAll_NamesVarDef,
                                                    inputAll_NamesCSVList=inputAll_NamesCSVList,

                                                    outputNamesCSVList=outputNamesCSVList, 
                                                    outputNamesVarDef=outputNamesVarDef,
                                                    outputPrinfPattern=outputPrinfPattern,
                                                    
                                                    calcOutputsArgs=calcOutputsArgs )


        return {'sourcecode' : self.template, 'manifest' : self.manifest, 'algorithm_sourcecode' : self._algorithm_code }

    def writeFiles(self, folder):

        with open( os.path.join( folder + '//simulation_manifest.json' ), 'w') as outfile:  
            json.dump(self.manifest, outfile)

    def build(self):
        pass

    def run(self):
        pass

Subclasses

Methods

def add_code_to_include(self, include_code_list: List[str] = [])
Expand source code
def add_code_to_include(self, include_code_list : List[str] = []):
    self._include_code_list = include_code_list
def build(self)
Expand source code
def build(self):
    pass
def code_gen(self)
Expand source code
def code_gen(self):

    # generate code for the algorithm
    self.manifest, self._algorithm_code = _generate_algorithm_code(
        self.compileResults, 
        self._enable_tracing, 
        self._includedSystems, 
        self._include_code_list
    )

    
    # TODO: iterate over all functions present in the API of the system
    # NOTE: Currently only the main functions are used: output, update, and reset
    #
    API_functions = self.main_command.command_to_put_main_system.API_functions

    #
    # make strings 
    # 

    def makeStrings(signals):
        names_CSV_list = cgh.signal_list_to_names_string(signals)
        names_var_def = cgh.define_variable_list_string(signals)
        printf_pattern = cgh.signalListHelper_printfPattern_string(signals)

        return names_CSV_list, names_var_def, printf_pattern


    # for the output signals
    # input1_NamesCSVList; list of output signals. e.g. 'y1, y2, y3' 
    outputNamesCSVList, outputNamesVarDef, outputPrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.outputSignals )

    # the inputs to the output command
    # input1_NamesCSVList: list of output signals. e.g. 'y1, y2, y3' 
    input1_NamesCSVList, input1_NamesVarDef, input1PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.outputCommand.inputSignals )

    # the inputs to the update command
    # input2_NamesCSVList list of output signals. e.g. 'u1, u2, u3' 
    input2_NamesCSVList, input2_NamesVarDef, input2_PrinfPattern = makeStrings( self.main_command.command_to_put_main_system.updateCommand.inputSignals )

    # all inputs
    # merge the list of inputs for the calcoutput and stateupdate function
    allInputs = list(set(self.main_command.command_to_put_main_system.outputCommand.inputSignals + self.main_command.command_to_put_main_system.updateCommand.inputSignals))
    inputAll_NamesCSVList, inputAll_NamesVarDef, inputAll_PrinfPattern = makeStrings( allInputs )

    # the names of input and output signals of the outputCommand combined
    calcOutputsArgs = cgh.signal_list_to_name_list( self.main_command.command_to_put_main_system.outputCommand.outputSignals + self.main_command.command_to_put_main_system.outputCommand.inputSignals )

    # fill in template
    self.template = Template(self.template).safe_substitute(  
                                                mainSimulationName = self.main_command.command_to_put_main_system.API_name,
                                                algorithmCode=self._algorithm_code,

                                                input1_NamesVarDef=input1_NamesVarDef,
                                                input1_NamesCSVList=input1_NamesCSVList,

                                                input2_NamesVarDef=input2_NamesVarDef,
                                                input2_NamesCSVList=input2_NamesCSVList,

                                                inputAll_NamesVarDef=inputAll_NamesVarDef,
                                                inputAll_NamesCSVList=inputAll_NamesCSVList,

                                                outputNamesCSVList=outputNamesCSVList, 
                                                outputNamesVarDef=outputNamesVarDef,
                                                outputPrinfPattern=outputPrinfPattern,
                                                
                                                calcOutputsArgs=calcOutputsArgs )


    return {'sourcecode' : self.template, 'manifest' : self.manifest, 'algorithm_sourcecode' : self._algorithm_code }
def get_algorithm_code(self)

Return only the code that implement the system and all sub systems

Expand source code
def get_algorithm_code(self):
    """
        Return only the code that implement the system and all sub systems
    """
    return self._algorithm_code
def include_systems(self, system: SystemLibraryEntry)
Expand source code
def include_systems(self, system : SystemLibraryEntry):
    self._includedSystems = system
def run(self)
Expand source code
def run(self):
    pass
def set_compile_results(self, compile_results: CompileResults)
Expand source code
def set_compile_results(self, compile_results : CompileResults ):
    self.compileResults = compile_results
    self.main_command = compile_results.command_to_execute
def writeFiles(self, folder)
Expand source code
def writeFiles(self, folder):

    with open( os.path.join( folder + '//simulation_manifest.json' ), 'w') as outfile:  
        json.dump(self.manifest, outfile)
class TargetWasm (enable_tracing=False)

generates code for the Webassemble runtime environment

https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html

Expand source code
class TargetWasm(TargetGenericCpp):
    """
        generates code for the Webassemble runtime environment

        https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html

    """

    def __init__(self, enable_tracing = False ):

        TargetGenericCpp.__init__(self, enable_tracing=enable_tracing)

        self.initCodeTemplate()

        
    def code_gen(self):

        # build I/O structs
        ioExport = self.generate_code_writeIO(self.main_command.command_to_put_main_system.outputCommand)
        ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.updateCommand)

        ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.resetCommand)

        self.template = Template(self.template).safe_substitute( ioExport=ioExport,
                                                                 inputConstAssignment=''    ) 

        # call helper to fill in some generic elements into the template
        code_gen_results = TargetGenericCpp.code_gen(self)

        self.sourceCode = self.template

        code_gen_results['sourcecode'] = self.sourceCode
        return code_gen_results



    def generate_code_writeIO__(self, command_API, inputOutput : int):

        if inputOutput == 1:
            structPrefix = 'Inputs_'
            signals = command_API.inputSignals

        elif inputOutput == 2:
            structPrefix = 'Outputs_'
            signals = command_API.outputSignals

        mainSimulationName = self.main_command.command_to_put_main_system.API_name

        lines = ''

        # Inputs
        structname = structPrefix + command_API.API_name 

        lines += 'value_object<' + mainSimulationName + '::' + structname + '>("' + mainSimulationName + '__' + structname + '")\n'

        for s in signals:
            fieldName = s.name

            lines += '.field("' + fieldName + '", &' + mainSimulationName + '::' + structname + '::' + fieldName + ')\n'

        lines += ';\n\n'


        return lines

    def generate_code_writeIO(self, command_API):
        return self.generate_code_writeIO__(command_API, 1) + self.generate_code_writeIO__(command_API, 2)


    def write_code(self, folder):

        TargetGenericCpp.writeFiles(self, folder)

        self.codeFolder = folder

        f = open( Path( folder ) / "main.cpp", "w")
        f.write( self.sourceCode )
        f.close()


    def build(self):

        buildCommand = 'emcc --bind -s MODULARIZE=1 -s EXPORT_NAME="ORTD_simulator" '  + os.path.join(self.codeFolder , "main.cpp") + " -g4 -s -o " + os.path.join( self.codeFolder , "main.js" )
        print("Running compiler: " + buildCommand)

        returnCode = os.system(buildCommand)

        print( "Compilation result: ", returnCode )


    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>
#include <emscripten/bind.h>

using namespace emscripten;

//
// implementation of $mainSimulationName
//

$algorithmCode

// Binding code
EMSCRIPTEN_BINDINGS(my_class_example) {
  class_<$mainSimulationName>("$mainSimulationName")
    .constructor<>()
    .function("resetStates", &$mainSimulationName::resetStates__)
    .function("calcResults_1", &$mainSimulationName::calcResults_1__)
    .function("updateStates", &$mainSimulationName::updateStates__)
    ;


// --------------------------------

$ioExport


}
            
        """        

Ancestors

Methods

def build(self)
Expand source code
def build(self):

    buildCommand = 'emcc --bind -s MODULARIZE=1 -s EXPORT_NAME="ORTD_simulator" '  + os.path.join(self.codeFolder , "main.cpp") + " -g4 -s -o " + os.path.join( self.codeFolder , "main.js" )
    print("Running compiler: " + buildCommand)

    returnCode = os.system(buildCommand)

    print( "Compilation result: ", returnCode )
def code_gen(self)
Expand source code
def code_gen(self):

    # build I/O structs
    ioExport = self.generate_code_writeIO(self.main_command.command_to_put_main_system.outputCommand)
    ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.updateCommand)

    ioExport += self.generate_code_writeIO(self.main_command.command_to_put_main_system.resetCommand)

    self.template = Template(self.template).safe_substitute( ioExport=ioExport,
                                                             inputConstAssignment=''    ) 

    # call helper to fill in some generic elements into the template
    code_gen_results = TargetGenericCpp.code_gen(self)

    self.sourceCode = self.template

    code_gen_results['sourcecode'] = self.sourceCode
    return code_gen_results
def generate_code_writeIO(self, command_API)
Expand source code
def generate_code_writeIO(self, command_API):
    return self.generate_code_writeIO__(command_API, 1) + self.generate_code_writeIO__(command_API, 2)
def generate_code_writeIO__(self, command_API, inputOutput: int)
Expand source code
def generate_code_writeIO__(self, command_API, inputOutput : int):

    if inputOutput == 1:
        structPrefix = 'Inputs_'
        signals = command_API.inputSignals

    elif inputOutput == 2:
        structPrefix = 'Outputs_'
        signals = command_API.outputSignals

    mainSimulationName = self.main_command.command_to_put_main_system.API_name

    lines = ''

    # Inputs
    structname = structPrefix + command_API.API_name 

    lines += 'value_object<' + mainSimulationName + '::' + structname + '>("' + mainSimulationName + '__' + structname + '")\n'

    for s in signals:
        fieldName = s.name

        lines += '.field("' + fieldName + '", &' + mainSimulationName + '::' + structname + '::' + fieldName + ')\n'

    lines += ';\n\n'


    return lines
def initCodeTemplate(self)
Expand source code
    def initCodeTemplate(self):

        #
        # template for main function in c++
        #

        self.template = """
            
#include <math.h>
#include <stdio.h>
#include <emscripten/bind.h>

using namespace emscripten;

//
// implementation of $mainSimulationName
//

$algorithmCode

// Binding code
EMSCRIPTEN_BINDINGS(my_class_example) {
  class_<$mainSimulationName>("$mainSimulationName")
    .constructor<>()
    .function("resetStates", &$mainSimulationName::resetStates__)
    .function("calcResults_1", &$mainSimulationName::calcResults_1__)
    .function("updateStates", &$mainSimulationName::updateStates__)
    ;


// --------------------------------

$ioExport


}
            
        """        
def write_code(self, folder)
Expand source code
def write_code(self, folder):

    TargetGenericCpp.writeFiles(self, folder)

    self.codeFolder = folder

    f = open( Path( folder ) / "main.cpp", "w")
    f.write( self.sourceCode )
    f.close()

Inherited members