Coder Social home page Coder Social logo

models's People

Contributors

grmanrodriguez avatar valegagge avatar

Watchers

 avatar  avatar

models's Issues

Code generation with For Iterator

I add here the info regarding the code generation using the For Iterator. Model used is here.

1st try: No For Iterator

First a simple model that does not use the For Iterator:

image

The model inside returns the third control mode always:

image

Simulink Generated Code: Empty ❌

void prototype_for_iterator_from_zero_step(void)
{
  /* (no output/update code required) */
}

2nd try: Adding Inports and Outports

Following this documentation (page 73) I changed the hard coded values for Inports and Outports:

image

Simulink Generated Code: With Code ✔️

void prototype_for_iterator_from_zero_step(void)
{
  /* Outport: '<Root>/y1' incorporates:
   *  Inport: '<Root>/u3'
   */
  prototype_for_iterator_from_z_Y.y1 =
    prototype_for_iterator_from_z_U.control_mode_p;
}

3rd try: Adding all the inputs

Now that I get an output I create a simple machine that adds all the inputs to the output:

image

I implement it using the Function Call paradigm first:

image

Simulink Generated Code: Code is Copy-Pasted ❓

void prototype_for_iterator_from_zero_step(void)
{
  /* Chart: '<Root>/Chart' incorporates:
   *  SubSystem: '<Root>/Function-Call Subsystem'
   */
  /* Chart: '<S2>/Chart' incorporates:
   *  Inport: '<Root>/u1'
   *  Outport: '<Root>/y1'
   */
  if (prototype_for_iterator_from__DW.is_active_c2_prototype_for_iter == 0U) {
    prototype_for_iterator_from__DW.is_active_c2_prototype_for_iter = 1U;
  } else if ((prototype_for_iterator_from_z_Y.y1 < 0) &&
             (prototype_for_iterator_from_z_U.u1.messages[0].control_mode <
              MIN_int32_T - prototype_for_iterator_from_z_Y.y1)) {
    /* Outport: '<Root>/y1' */
    prototype_for_iterator_from_z_Y.y1 = MIN_int32_T;
  } else if ((prototype_for_iterator_from_z_Y.y1 > 0) &&
             (prototype_for_iterator_from_z_U.u1.messages[0].control_mode >
              MAX_int32_T - prototype_for_iterator_from_z_Y.y1)) {
    /* Outport: '<Root>/y1' */
    prototype_for_iterator_from_z_Y.y1 = MAX_int32_T;
  } else {
    /* Outport: '<Root>/y1' incorporates:
     *  Inport: '<Root>/u1'
     */
    prototype_for_iterator_from_z_Y.y1 +=
      prototype_for_iterator_from_z_U.u1.messages[0].control_mode;
  }

  if (prototype_for_iterator_from__DW.is_active_c2_prototype_for_iter == 0U) {
    prototype_for_iterator_from__DW.is_active_c2_prototype_for_iter = 1U;
  } else if ((prototype_for_iterator_from_z_Y.y1 < 0) &&
             (prototype_for_iterator_from_z_U.u1.messages[1].control_mode <
              MIN_int32_T - prototype_for_iterator_from_z_Y.y1)) {
    /* Outport: '<Root>/y1' */
    prototype_for_iterator_from_z_Y.y1 = MIN_int32_T;
  } else if ((prototype_for_iterator_from_z_Y.y1 > 0) &&
             (prototype_for_iterator_from_z_U.u1.messages[1].control_mode >
              MAX_int32_T - prototype_for_iterator_from_z_Y.y1)) {
    /* Outport: '<Root>/y1' */
    prototype_for_iterator_from_z_Y.y1 = MAX_int32_T;
  } else {
    /* Outport: '<Root>/y1' incorporates:
     *  Inport: '<Root>/u1'
     */
    prototype_for_iterator_from_z_Y.y1 +=
      prototype_for_iterator_from_z_U.u1.messages[1].control_mode;
  }

  /* I remove the other two repetitions for brevity*/

  /* End of Chart: '<S2>/Chart' */
}

This goes against what we had originally thought. I implement the same block using the For Iterator to see the output. I write the machine that adds the inputs again from scratch to prevent any potential errors from copying the models:

image

image

Simulink Generated Code: Uses a For Loop ❓

void prototype_for_iterator_from_zero_step(void)
{
  int32_T s1_iter;

  /* Outputs for Iterator SubSystem: '<Root>/For Iterator Subsystem' incorporates:
   *  ForIterator: '<S1>/For Iterator'
   */
  /* Selector: '<S1>/Selector' */
  for (s1_iter = 0; s1_iter < 5; s1_iter++) {
    /* Chart: '<S1>/Chart' incorporates:
     *  Inport: '<Root>/u1'
     *  Outport: '<Root>/y1'
     */
    if (prototype_for_iterator_from__DW.is_active_c4_prototype_for_iter == 0U) {
      prototype_for_iterator_from__DW.is_active_c4_prototype_for_iter = 1U;
    } else {
      int32_T q1;
      q1 = prototype_for_iterator_from_z_U.u1.messages[s1_iter].control_mode;
      if ((prototype_for_iterator_from_z_Y.y1 < 0) && (q1 < MIN_int32_T
           - prototype_for_iterator_from_z_Y.y1)) {
        prototype_for_iterator_from_z_Y.y1 = MIN_int32_T;
      } else if ((prototype_for_iterator_from_z_Y.y1 > 0) && (q1 > MAX_int32_T -
                  prototype_for_iterator_from_z_Y.y1)) {
        prototype_for_iterator_from_z_Y.y1 = MAX_int32_T;
      } else {
        prototype_for_iterator_from_z_Y.y1 += q1;
      }
    }

    /* End of Chart: '<S1>/Chart' */
  }

  /* End of Selector: '<S1>/Selector' */
  /* End of Outputs for SubSystem: '<Root>/For Iterator Subsystem' */
}

So the behavior is opposite to what we expected. The For Iterator creates the for loop and the Function Call copy-pastes the code.

At this point I believe the behavior depends on what the machine inside is doing when it's called. So I try again to create a miniature Supervisor.

4th try: Miniature Supervisor

I swap the adding machine for one similar to our simplified supervisor:

image

Again, I generate first using the Function Call paradigm:

image

Simulink Generated Code: Code is Copy-Pasted ❓

void prototype_for_iterator_from_zero_step(void)
{
  /* Chart: '<Root>/Chart1' incorporates:
   *  SubSystem: '<Root>/Function-Call Subsystem1'
   */
  /* Chart: '<S2>/Chart' incorporates:
   *  Inport: '<Root>/u1'
   */
  if (prototype_for_iterator_from__DW.is_active_c6_prototype_for_iter == 0U) {
    prototype_for_iterator_from__DW.is_active_c6_prototype_for_iter = 1U;
    prototype_for_iterator_from__DW.is_c6_prototype_for_iterator_fr =
      prototype_for_iterator__IN_idle;

    /* Outport: '<Root>/y2' incorporates:
     *  Inport: '<Root>/u1'
     */
    prototype_for_iterator_from_z_Y.y2 =
      prototype_for_iterator_from_z_U.u1.messages[0].control_mode;
  } else {
    switch (prototype_for_iterator_from__DW.is_c6_prototype_for_iterator_fr) {
     case prototype_for_iterator_IN_fault:
      if (prototype_for_iterator_from_z_U.u1.messages[0].control_mode == 0) {
        prototype_for_iterator_from__DW.is_c6_prototype_for_iterator_fr =
          prototype_for_iterator__IN_idle;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.u1.messages[0].control_mode;
      }
      break;

     case prototype_for_iterator__IN_idle:
      if (prototype_for_iterator_from_z_U.u1.messages[0].control_mode == 1) {
        prototype_for_iterator_from__DW.is_c6_prototype_for_iterator_fr =
          prototype_for_iterat_IN_running;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.u1.messages[0].control_mode;
      }
      break;

     default:
      /* case IN_running: */
      if (prototype_for_iterator_from_z_U.u1.messages[0].control_mode == -1) {
        prototype_for_iterator_from__DW.is_c6_prototype_for_iterator_fr =
          prototype_for_iterator_IN_fault;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.u1.messages[0].control_mode;
      }
      break;
    }
  }

  /* I remove the other three repetitions for brevity */
  }

I again replicate the supervisor and implement using the For Iterator:

image

Simulink Generated Code: Code is Copy-Pasted ❓

void prototype_for_iterator_from_zero_step(void)
{
  /* Outputs for Iterator SubSystem: '<Root>/For Iterator Subsystem1' incorporates:
   *  ForIterator: '<S1>/For Iterator'
   */
  /* Chart: '<S1>/Chart' incorporates:
   *  Inport: '<Root>/input_1'
   *  Selector: '<S1>/Selector'
   */
  if (prototype_for_iterator_from__DW.is_active_c7_prototype_for_iter == 0U) {
    prototype_for_iterator_from__DW.is_active_c7_prototype_for_iter = 1U;
    prototype_for_iterator_from__DW.is_c7_prototype_for_iterator_fr =
      prototype_for_iterator__IN_init;

    /* Outport: '<Root>/y2' incorporates:
     *  Inport: '<Root>/input_1'
     *  Selector: '<S1>/Selector'
     */
    prototype_for_iterator_from_z_Y.y2 =
      prototype_for_iterator_from_z_U.input_1.messages[0].control_mode;
  } else {
    switch (prototype_for_iterator_from__DW.is_c7_prototype_for_iterator_fr) {
     case prototype_for_iterator_IN_fault:
      if (prototype_for_iterator_from_z_U.input_1.messages[0].control_mode == 0)
      {
        prototype_for_iterator_from__DW.is_c7_prototype_for_iterator_fr =
          prototype_for_iterator__IN_init;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.input_1.messages[0].control_mode;
      }
      break;

     case prototype_for_iterator__IN_init:
      if (prototype_for_iterator_from_z_U.input_1.messages[0].control_mode == 1)
      {
        prototype_for_iterator_from__DW.is_c7_prototype_for_iterator_fr =
          prototype_for_iterat_IN_running;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.input_1.messages[0].control_mode;
      }
      break;

     default:
      /* case IN_running: */
      if (prototype_for_iterator_from_z_U.input_1.messages[0].control_mode == -1)
      {
        prototype_for_iterator_from__DW.is_c7_prototype_for_iterator_fr =
          prototype_for_iterator_IN_fault;

        /* Outport: '<Root>/y2' */
        prototype_for_iterator_from_z_Y.y2 =
          prototype_for_iterator_from_z_U.input_1.messages[0].control_mode;
      }
      break;
    }
  }

  /* I remove the others for brevity */
  
  }

confused

Conclusions so far:

  • Whether the code is generated or not depends on the existance of inputs and outputs for the model. If there are none, Simulink sees it as internal operations that don't affect anything and doesn't generate the code.
    I assume in our case having two different blocks in the Function Call made it work like input/output, while in the For Iterator it decided not to need to generate because there was one single block with no in/outports. In any case, a block with inputs and outputs will always generate.

  • It is unclear still when the code generator decides to implement a for loop or copy-pasting. I assume it depends on the optimization and the complexity of the operations it will create. The only thing we can be sure is that it's not as simple as Function Call = For Loop and For Iterator = Copy-Paste

cc @valegagge @vvasco

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.