Sim_Bus_in_Your_Project - nasa/gunns GitHub Wiki

{{>toc}}

Sim Bus in Your Project

You can use a similar approach to the SIM_simbus_example sim, described in Example_Sim_Bus_Setup, in your projects. You can copy and re-use most of these files out of gunns/ into your own projects, with a little modification. Once you get it set up and working on your project, adding new interfaces becomes very easy.

First of all, remember that your sim folder should not be inside of gunns/ but rather in a more project-specific location. In general, you should not put any project-specific files inside gunns/. This leaves your gunns/ repo uncluttered and only containing our official GUNNS release stuff.

The following lists the files you need in your project to use the sim bus, and how to modify the example files from gunns/:

Sim Bus Source Repository (SIMBUS_HOME)

The first thing you need is access to the Sim Bus source code. We have multiple versions in separate svn and git repositories in the Trick Lab. Our example sim uses the version in the icd-tools git repository. You can clone it at [email protected]:icd-tools.git. It also exists in the nexsys_common svn repository at https://tricklab.jsc.nasa.gov/svn/repos/nexsys_common/trunk, and then inside nexsys_common/models/subsystems/SimBus/. These versions are normally identical, and either one will suffice for our use with GUNNS. Use the one that is most convenient for you.

Inside these repositories is the Sim Bus code used to generate the Sim Bus in your sim. It’s mostly python code. The most important file we use is src/icdgen.py.

When you have access to this code, you’ll assign the folder to the SIMBUS_HOME system variable in the S_overides.mk script below.

In Your ICD_HOME Folder:

Your project should have some folder to contain the following files. The folder can have any name and be anywhere you want. In ER, we usually keep it in a project-specific models/ or sims/ folder. In the GUNNS Sim Bus example sim, this is at gunns/sims/icd/. This folder is assigned to the system variable ICD_HOME in your sim’s S_overrides.mk file, described below.

ICD Files

These define all the variable-to-variable transfers (reads & writes) that your sim bus will do. Here is an example of what they look like.

Here is a brief rundown of the most important rules to follow in these files:

  • The columns are tab-delimited, which exactly one tab between columns. The SIM_OBJECT column is tricky — it is actually 2 fields separated by a space: the sim object type followed by the sim object instance name.
  • Each SYS/BUS/SUBSYS/VAR NAME should only have one WRITE to it, and any number of READS. Sim Bus allows one-to-one and one-to-many communication, but not many-to-one.
  • Each READ target (SIM_VAR_NAME) must never have more than one READ to it.
  • The reads and writes happen at the value in the RATE column (usually #DEFINED in the sims’s S_define file). This rate should match the rate at which the model updates. See the Test.sm sim object below.
  • The WRITE to READ terms must have the same TYPE (double to double, int to int, etc).
  • The units (K) are important because the Sim Bus will automatically convert units for you if it recognizes the conversion. Only some conversions are recognized. To skip units conversions, you can specify (—) for the unit type, and the units here don’t have to match the units in the variable’s Trick declaration in your model code.
  • The WRITE and READ lines for a single data transfer don’t have to reside in the same .txt file. You can make as many of these files as you like, but we recommend organizing them in some sensible way.

icd_generate

See these two sections: you should modify these to create lists of your ICD files (above) and include them and different combinations of them in each sim. This script can service multiple SIM_ folders, with a separate icd_generate(, ) command for each. This example builds your SIM_your_sim using 3 ICD files from this same folder.

This is a python language script. Feel free to deviate from this code if you’d like to do it another way.


#########################################################################
##     Common ICD lists can be placed here                             ##
##     Note: please be careful when adjusting these lists, they may    ##
##           be referenced in multiple places below                    ##
#########################################################################
your_icds = [
   rdir+'/YOUR_ICD_1.txt',
   rdir+'/YOUR_ICD_2.txt',
   rdir+'/YOUR_ICD_3.txt',
]

#########################################################################
##     Specific calls to tools go here                                 ##
##     Note: Developers are free to adjust the calls below to meet     ##
##           their needs                                               ##
#########################################################################
#-----------------------------------------------------------------------
# SIM_your_sim
icds = [

] + your_icds
icd_generate(icds, 'SIM_your_sim')

simobj_to_thread_mapping.txt

You must have this file in your ICD_HOME folder. This file assigns sim objects or their components (i.e. GUNNS networks) to execution threads. This ensures that all the simbus writes/reads to/from a particular network happen before/after that network executes, in the proper order in each thread. Below is an example of what it looks like. We recommend copying the gunns/ example and modifying it for your project.

FLUID_THREAD     testSimObject_fluid
ELECT_THREAD     testSimObject_basic
THERMAL_THREAD   testSimObject_thermal
  • Each row in the file assigns one object to a thread name, and the format is , separated by white space. The object is an actual instance name, not a type. The object can be a sim object, or a sub-component, with an underscore “_” character replacing a period “.” to represent parent.child relationships. In this example, fluid, basic, and thermal are all names of network instances within the testSimObject sim object instance. Thus we have assigned the 3 networks in testSimObject all to their own threads.
  • Multiple objects can be assigned to the same thread. Just give them a new row with the same . You can put any object in any thread that you want. However…
  • All objects in the same thread must have the same execution rate, or simbus will complain in H&S. This is controlled in the Sim Object .sm file, described below.
  • Order of the rows doesn’t matter.
  • MAIN_THREAD is the name of the Trick sim’s main thread, and is always present in the sim. You can add your objects to that thread if you want; however we recommend making your own thread(s) to put your models in, to ensure proper syncing between the simbus and your models at their respective execution rates.

Note that this file does not assign threads to different CPU’s. By default, Trick runs all threads on the same CPU and it takes additional set-up to change that, not covered here.

Your Sim Object .sm Files:

Any sim object that contains models that have Sim Bus interfaces must assign those models’ Trick run jobs to the proper thread. This ensures that your networks execute in the same threads that you defined for the sim bus in your simobj_to_thread_mapping.txt file above.

We provide an example code pattern that does this in gunns/sims/S_modules/Test.sm. We recommend using the same pattern in your sim objects. Here are the sections of the .sm that you need to modify for your project:

First, the sim object class has an int attribute to hold the thread ID for each separate thread being used by the sim object and its components (networks):


class TestSimObject: public Trick::SimObject
{
    public:
        int                  threadIdFluid;        /**< (--) Thread ID for the fluid network */
        int                  threadIdBasic;        /**< (--) Thread ID for the basic network */
        int                  threadIdThermal;      /**< (--) Thread ID for the thermal network */
    .
    .
    .

Then we pass the thread ID’s as arguments to the sim object class constructor and store these values in the class attributes:


        TestSimObject(int thread_id_fluid   = 0,
                      int thread_id_basic   = 0,
                      int thread_id_thermal = 0)
            :
            threadIdFluid(thread_id_fluid),
            threadIdBasic(thread_id_basic),
            threadIdThermal(thread_id_thermal),
    .
    .
    .

Finally, the networks are executed in their assigned threads with the “C” syntax in the Trick run jobs:


            CthreadIdFluid   (ECLSS_LO, "scheduled") fluid.update(ECLSS_LO);
            CthreadIdBasic   (ECLSS_LO, "scheduled") basic.update(ECLSS_LO);
            CthreadIdThermal (ECLSS_LO, "scheduled") thermal.update(ECLSS_LO);
        }
    .
    .
    .

In your SIM_ Folder:

S_overrides.mk

Copy this file over from /gunns/sims/SIM_simbus_example/S_overrides.mk and modify it like so:

The first statement defines a system variable ICD_HOME that holds the location of the folder containing your ICD.txt, icd_generate, and simobj_to_thread_mapping.txt files (described above). In our example, this is at gunns/sims/icd, but you want to modify this to your folder’s path. For example:

# You should modify this to point to the folder containing your sim bus ICD .txt files
# and icd_generate file:
ICD_HOME = ${YOUR_PROJECT_HOME}/models/icd

The second statement defines an system variable SIMBUS_HOME that holds the locations of the folder where your Sim Bus source code is (described above). In our example, we point to ${HOME}/repos/icd-tools, but you want to modify this to your folder’s path. For example:

# You should modify this to point to your Sim Bus source code location:
SIMBUS_HOME ?= ${YOUR_PROJECT_HOME}/external_repos/icd-tools

The third statements add the parent folder containing the SIM_ folder to the relevant Trick include paths. This is needed for the simbus to compile. Modify this as necessary:

# You should modify this to point to the SIM_ folder's parent folder as necessary.
# This is the folder containing the SIM_ folder that this file resides in.
# The thread_safe_bus/simbus_simobj.sm requires that the parent folder
# be in the Trick include paths.
TRICK_CFLAGS   += -I${GUNNS_HOME}/sims
TRICK_CXXFLAGS += -I${GUNNS_HOME}/sims

S_simbus.mk

You shouldn’t have to modify this file — just copy it over from gunns/sims/SIM_simbus_example/S_simbus.mk.

S_define

Here’s where you instantiate the Sim Bus and your sim objects. The example in gunns/sims/SIM_simbus_example/S_define is good to copy from and modify to work in your project.

The S_define does two important things related to our use of the sim bus.

First, you include the built Sim Bus and thread definition code into your sim. You want to keep this section intact:

// Needed for sim bus multithreading
#include "../S_modules/ChildThreadHandler.sm"
#include "thread_safe_bus/thread_map.sm"

// Simbus sim object
#include "thread_safe_bus/simbus_simobj.sm"

Secondly, you instantiate your model sim objects with arguments for their needed thread ID’s, like below. You’ll modify this to instantiate your sim objects with their needed threading arguments:

// Model sim objects.
#include "../S_modules/YourSimObject.sm"
YourSimObject yourSimObject(CTH.getThreadId(gyourSimObject_yourNetwork1_Thread),
                            CTH.getThreadId(gtestSimObject_yourNetwork2_Thread),
                            .
                            .
                            .);

Note the CTH.getThreadId(gyourSimObject_…_Thread) calls — CTH is the Child Thread Handler defined in the ChildThreadHandler.sm, and the gyourSimObject_…_Thread arguments are global strings corresponding to your thread-object assingments in simobj_to_thread_mapping.txt above.

These strings are defined in thread_safe_bus/thread_map.sm, which is generated when you build the sim bus. But since thread_map.sm isn’t generated until you build, how can you know what these string names are to put in your S_define before you build? Easy: the format of the string names is always: g_Thread.

Making and Cleaning

Now that all your files are ready to go, it’s time to build! The Sim Bus is automatically built along with the sim when you do Trick’s normal $ CP command to build the sim. Whenever changing any of your Sim Bus interfaces in the ICD_HOME files, it is a good idea to do a $ make clean; or $ make spotless; command before $ CP. Additionally, you can do a $ make clean_icd; to clear out all of the built Sim Bus stuff in the thread_safe_bus folder.

⚠️ **GitHub.com Fallback** ⚠️