/**
   * Generate the OIL/C code for a processor
   *
   * @param processor L'AST du processeur.
   */
  private void genCpu(ProcessSubcomponent ps) {

    Cpu cpu = oil.getCpu();
    Os os = cpu.getOs();
    _mainHCode.addOutputNewline("#include \"kernel.h\"");
    _mainHCode.addOutputNewline("#include \"kernel_id.h\"");

    /* Generate code for threads process */
    ProcessImplementation pi = (ProcessImplementation) ps.getComponentImplementation();
    cpu.addAllDataSubcomponent(pi.getOwnedDataSubcomponents());
    buildDataAccessMapping(pi, dataAccessMapping);

    EList<ThreadSubcomponent> subcomponents = pi.getOwnedThreadSubcomponents();

    _mainCCode.addOutputNewline("/*********** Tasks ***********/");
    for (ThreadSubcomponent threadSubcomponent : subcomponents) {
      genTask(ps, threadSubcomponent, COUNTER_NAME);
      genCTask(ps, threadSubcomponent);
    }

    /* Generate code for OS */

    /*
     * If one data contains Concurrency_Control_Protocol at
     * Priority_Ceiling STATUS => EXTENDED
     */
    if (os.getStatus() == Status.STANDARD) {
      ProcessImplementation processImpl = (ProcessImplementation) ps.getComponentImplementation();

      EList<Subcomponent> subcmpts = processImpl.getAllSubcomponents();

      for (Subcomponent s : subcmpts) {
        if (s instanceof DataSubcomponent) {
          String value = PropertyUtils.getEnumValue(s, "Concurrency_Control_Protocol");
          if (value != null) {
            if (value.equals("Priority_Ceiling")) {
              os.setStatus(Status.EXTENDED);
              break;
            }
          } else {
            String errMsg = "cannot fetch Concurrency_Control_Protocol for \'" + s.getName() + '\'';
            _LOGGER.error(errMsg);
            ServiceProvider.SYS_ERR_REP.error(errMsg, true);
          }
        }
      }
    }

    List<String> modeIdList = getProcessModesIdentifiers(ps);
    cpu.setAppmode(modeIdList);

    cpu.setName(ps.getName());
    genOsConfig(ps);
  }
  /**
   * Configuration de l'OS
   *
   * @param processSubcomponent
   */
  private void genOsConfig(ProcessSubcomponent processSubcomponent) {

    /* C Data declaration */
    Os os = oil.getCpu().getOs();
    os.setName("config");
    os.setAppName(processSubcomponent.getName());

    _mainCCode.addOutputNewline("/*********** Data ***********/");
    ProcessImplementation pi =
        (ProcessImplementation) processSubcomponent.getComponentImplementation();
    for (DataSubcomponent ds : pi.getOwnedDataSubcomponents()) {
      if (ds.getSubcomponentType().getName().equalsIgnoreCase(EVENTDATA_PORT_TYPE)
          || ds.getSubcomponentType().getName().equalsIgnoreCase(DATA_PORT_TYPE)) {
        _mainHCode.addOutputNewline("DeclareResource(" + ds.getName() + "_rez);");
        //			  _mainHCode.addOutputNewline("extern const ResourceType "+ds.getName()+"_rez;");
      }
      if (ds.getSubcomponentType().getName().equalsIgnoreCase(EVENTDATA_PORT_TYPE)) {
        _mainHCode.addOutputNewline("DeclareEvent(" + ds.getName() + "_evt);");
        //			  _mainHCode.addOutputNewline("extern const EventMaskType "+ds.getName()+"_evt;");
      }
    }

    _mainCCode.addOutputNewline("");
  }
  /**
   * Génération du code OIL d'un thread.
   *
   * @param ps Le processeur conteannt les threads.
   * @param thread L'AST du thread.
   * @param counterName Le nom du compteur sur lequel la tâche se synchronise
   */
  private void genTask(ProcessSubcomponent ps, ThreadSubcomponent thread, String counterName) {

    final Cpu cpu = oil.getCpu();
    final Counter counter = cpu.getCounter();
    final Os os = cpu.getOs();

    /*
     * If one thread/device contains Initialize_Entrypoint STARTUPHOOK =
     * true
     */
    if (os.getStartupHook() == false) {
      if (PropertyUtils.findPropertyAssociation("Initialize_Entrypoint", thread) != null)
        os.setStartupHook(true);
    }

    /*
     * If one thread/device contains Finalize_Entrypoint SHUTDOWNHOOK = true
     */
    if (os.getShutdownHook() == false) {
      if (PropertyUtils.findPropertyAssociation("Finalize_Entrypoint", thread) != null)
        os.setShutdownHook(true);
    }

    /* Begin task */

    Task task = new Task();
    Schedule schedule;
    Long stackSize = PropertyUtils.getIntValue(thread, "Stack_Size");
    Long priority = PropertyUtils.getIntValue(thread, "Priority");

    if (priority == null) {
      String errMsg = "cannot fetch Priority for \'" + thread.getName() + '\'';
      _LOGGER.error(errMsg);
      ServiceProvider.SYS_ERR_REP.error(errMsg, true);
      priority = -1l;
    }

    if (stackSize == null) {
      stackSize = THREAD_STACKSIZE;
      String msg = "set default stack size for \'" + thread.getName() + '\'';
      _LOGGER.warn(msg);
      ServiceProvider.SYS_ERR_REP.warning(msg, true);
    }

    Boolean scheduler = PropertyUtils.getBooleanValue(ps, "Preemptive_Scheduler");
    if (scheduler == null) {
      schedule = Schedule.FULL;
      String msg = "set default scheduler for \'" + thread.getName() + '\'';
      _LOGGER.warn(msg);
      ServiceProvider.SYS_ERR_REP.warning(msg, true);
    } else {
      if (scheduler) schedule = Schedule.FULL;
      else schedule = Schedule.NON;
    }

    task.setName(thread.getName());
    task.setPriority(priority.intValue());
    task.setActivation(THREAD_ACTIVATION);

    task.setSchedule(schedule);
    task.setStacksize(stackSize.intValue());

    ThreadImplementation ti = (ThreadImplementation) thread.getSubcomponentType();
    ThreadType tt = (ThreadType) ti.getType();
    for (DataAccess da : this.dataAccessMapping.keySet()) {
      for (DataAccess tda : tt.getOwnedDataAccesses()) {
        if (tda.equals(da)) {
          task.addResource(this.dataAccessMapping.get(tda));
          if (da.getDataFeatureClassifier().getName().equalsIgnoreCase(EVENTDATA_PORT_TYPE))
            task.addEvent(this.dataAccessMapping.get(da));
        }
      }
    }

    /* End task */

    /*
     * Generate alarme associated to periodic tasks
     */
    {
      String dispatchProtocol = PropertyUtils.getEnumValue(thread, "Dispatch_Protocol");

      if ("Periodic".equals(dispatchProtocol)) {

        /* Begin Alarm */

        Long period = PropertyUtils.getIntValue(thread, "Period");
        if (period == null) {
          String errMsg = "cannot fetch Period for " + thread.getName();
          _LOGGER.error(errMsg);
          ServiceProvider.SYS_ERR_REP.error(errMsg, true);
          period = -1l;
        }

        int alarmTime = 0;
        try {
          alarmTime = 1;
        } catch (Exception exc) {
        }

        List<String> inModeIdList = new ArrayList<String>();
        ProcessImplementation pi = (ProcessImplementation) ps.getSubcomponentType();
        if (pi.getOwnedModes().isEmpty()) inModeIdList.add(MAIN_APP_MODE);
        else {
          if (thread.getAllInModes().isEmpty()) {
            for (Mode m : pi.getOwnedModes()) {
              inModeIdList.add(m.getName());
            }
          } else {
            for (Mode m : thread.getAllInModes()) {
              inModeIdList.add(m.getName());
            }
          }
        }

        Alarm alarm = new Alarm(counter, task, cpu, inModeIdList);

        alarm.setName("wakeUp" + thread.getName());
        alarm.setAction(Action.ACTIVATETASK);
        alarm.setAutostart(true);
        alarm.setAlarmTime(alarmTime);
        alarm.setCycleTime(period.intValue());

        task.setAutostart(false);

        cpu.addPeriodicTask(new PeriodicTask(task, alarm));
        /* End Alarm */
      } else {
        task.setAutostart(true);
        cpu.addTask(task);
      }
    }
  }