LCOV - code coverage report
Current view: top level - core/src/serial - serial.c Hit Total Coverage
Test: ROOT-Sim develop Documentation Coverage Lines: 11 14 78.6 %
Date: 2021-03-02 11:24:52

          Line data    Source code
       1           1 : /**
       2             :  * @file serial/serial.c
       3             :  *
       4             :  * @brief Sequential simlation engine
       5             :  *
       6             :  * SPDX-FileCopyrightText: 2008-2021 HPDCS Group <rootsim@googlegroups.com>
       7             :  * SPDX-License-Identifier: GPL-3.0-only
       8             :  */
       9             : #include <serial/serial.h>
      10             : 
      11             : #include <arch/timer.h>
      12             : #include <core/core.h>
      13             : #include <core/init.h>
      14             : #include <datatypes/heap.h>
      15             : #include <lib/lib.h>
      16             : #include <log/stats.h>
      17             : #include <lp/msg.h>
      18             : #include <mm/msg_allocator.h>
      19             : 
      20             : #include <stdlib.h>
      21             : 
      22             : /// The LP context for the serial runtime
      23           1 : struct s_lp_ctx {
      24             :         /// The context for the model development libraries
      25             :         struct lib_ctx lib_ctx;
      26             : #if LOG_DEBUG >= LOG_LEVEL
      27             :         /// The logical time of the last processed event by this LP
      28           1 :         simtime_t last_evt_time;
      29             : #endif
      30             :         /// The last evaluation of the termination predicate for this LP
      31           1 :         bool terminating;
      32             : };
      33             : 
      34             : /// The array of all the simulation LP contexts
      35           1 : static struct s_lp_ctx *s_lps;
      36             : /// The context of the currently processed LP
      37           1 : static struct s_lp_ctx *s_current_lp;
      38             : /// The messages queue of the serial runtime
      39           1 : static binary_heap(struct lp_msg *) queue;
      40             : #if LOG_DEBUG >= LOG_LEVEL
      41             : /// Used for debugging possibly inconsistent models
      42             : static simtime_t current_evt_time;
      43             : #endif
      44             : 
      45             : void serial_model_init(void)
      46             : {
      47             :         struct s_lp_ctx tmp_lp = {0};
      48             :         s_current_lp = &tmp_lp;
      49             :         s_lps = s_current_lp - n_lps;
      50             : 
      51             :         lib_lp_init();
      52             :         ProcessEvent(0, 0, MODEL_INIT, NULL, 0, NULL);
      53             :         lib_lp_fini();
      54             : }
      55             : 
      56             : /**
      57             :  * @brief Initializes the serial simulation environment
      58             :  */
      59           1 : static void serial_simulation_init(void)
      60             : {
      61             :         stats_global_init();
      62             :         stats_init();
      63             :         msg_allocator_init();
      64             :         heap_init(queue);
      65             :         lib_global_init();
      66             :         serial_model_init();
      67             : 
      68             :         s_lps = mm_alloc(sizeof(*s_lps) * n_lps);
      69             :         memset(s_lps, 0, sizeof(*s_lps) * n_lps);
      70             : 
      71             :         for (uint64_t i = 0; i < n_lps; ++i) {
      72             :                 s_current_lp = &s_lps[i];
      73             :                 lib_lp_init();
      74             : #if LOG_DEBUG >= LOG_LEVEL
      75             :                 s_lps[i].last_evt_time = -1;
      76             : #endif
      77             :                 ProcessEvent(i, 0, LP_INIT, NULL, 0, s_lps[i].lib_ctx.state_s);
      78             :         }
      79             : }
      80             : 
      81             : /**
      82             :  * @brief Finalizes the serial simulation environment
      83             :  */
      84           1 : static void serial_simulation_fini(void)
      85             : {
      86             :         for (uint64_t i = 0; i < n_lps; ++i) {
      87             :                 s_current_lp = &s_lps[i];
      88             :                 ProcessEvent(i, 0, LP_FINI, NULL, 0, s_lps[i].lib_ctx.state_s);
      89             :                 lib_lp_fini();
      90             :         }
      91             : 
      92             :         ProcessEvent(0, 0, MODEL_FINI, NULL, 0, NULL);
      93             : 
      94             :         for (array_count_t i = 0; i < array_count(queue); ++i) {
      95             :                 msg_allocator_free(array_get_at(queue, i));
      96             :         }
      97             : 
      98             :         mm_free(s_lps);
      99             : 
     100             :         lib_global_fini();
     101             :         heap_fini(queue);
     102             :         msg_allocator_fini();
     103             :         stats_global_fini();
     104             : }
     105             : 
     106             : /**
     107             :  * @brief Runs the serial simulation
     108             :  */
     109           1 : static void serial_simulation_run(void)
     110             : {
     111             :         timer_uint last_vt = timer_new();
     112             :         uint64_t to_terminate = n_lps;
     113             : 
     114             :         while (likely(!heap_is_empty(queue))) {
     115             :                 const struct lp_msg *cur_msg = heap_min(queue);
     116             :                 struct s_lp_ctx *this_lp = &s_lps[cur_msg->dest];
     117             :                 s_current_lp = this_lp;
     118             : 
     119             : #if LOG_DEBUG >= LOG_LEVEL
     120             :                 if (log_can_log(LOG_DEBUG)) {
     121             :                         if(cur_msg->dest_t == s_current_lp->last_evt_time)
     122             :                                 log_log(
     123             :                                         LOG_DEBUG,
     124             :                                         "LP %u got two consecutive events with same timestamp %lf",
     125             :                                         cur_msg->dest,
     126             :                                         cur_msg->dest_t
     127             :                                 );
     128             :                         s_current_lp->last_evt_time = cur_msg->dest_t;
     129             :                 }
     130             :                 current_evt_time = cur_msg->dest_t;
     131             : #endif
     132             : 
     133             :                 stats_time_start(STATS_MSG_PROCESSED);
     134             : 
     135             :                 ProcessEvent(
     136             :                         cur_msg->dest,
     137             :                         cur_msg->dest_t,
     138             :                         cur_msg->m_type,
     139             :                         cur_msg->pl,
     140             :                         cur_msg->pl_size,
     141             :                         s_current_lp->lib_ctx.state_s
     142             :                 );
     143             : 
     144             :                 stats_time_take(STATS_MSG_PROCESSED);
     145             : 
     146             :                 bool can_end = CanEnd(cur_msg->dest, s_current_lp->lib_ctx.state_s);
     147             : 
     148             :                 if (can_end != s_current_lp->terminating) {
     149             :                         s_current_lp->terminating = can_end;
     150             :                         to_terminate += 1 - ((int)can_end * 2);
     151             : 
     152             :                         if (unlikely(!to_terminate)) {
     153             :                                 stats_on_gvt(cur_msg->dest_t);
     154             :                                 break;
     155             :                         }
     156             :                 }
     157             : 
     158             :                 if (global_config.gvt_period <= timer_value(last_vt)) {
     159             :                         stats_on_gvt(cur_msg->dest_t);
     160             :                         if (unlikely(cur_msg->dest_t >=
     161             :                                 global_config.termination_time))
     162             :                                 break;
     163             :                         last_vt = timer_new();
     164             :                 }
     165             : 
     166             :                 msg_allocator_free(heap_extract(queue, msg_is_before));
     167             :         }
     168             : 
     169             :         stats_dump();
     170             : }
     171             : 
     172           0 : void ScheduleNewEvent(lp_id_t receiver, simtime_t timestamp,
     173             :         unsigned event_type, const void *payload, unsigned payload_size)
     174             : {
     175             : #if LOG_DEBUG >= LOG_LEVEL
     176             :         if (log_can_log(LOG_DEBUG) && current_evt_time > timestamp)
     177             :                 log_log(LOG_DEBUG, "Sending a message in the PAST!");
     178             : #endif
     179             : 
     180             :         struct lp_msg *msg = msg_allocator_pack(
     181             :                 receiver, timestamp, event_type, payload, payload_size);
     182             :         heap_insert(queue, msg_is_before, msg);
     183             : }
     184             : 
     185             : /**
     186             :  * @brief Handles a full serial simulation runs
     187             :  */
     188           1 : void serial_simulation(void)
     189             : {
     190             :         log_log(LOG_INFO, "Initializing serial simulation");
     191             :         serial_simulation_init();
     192             :         stats_global_time_take(STATS_GLOBAL_INIT_END);
     193             : 
     194             :         stats_global_time_take(STATS_GLOBAL_EVENTS_START);
     195             :         log_log(LOG_INFO, "Starting simulation");
     196             :         serial_simulation_run();
     197             :         stats_global_time_take(STATS_GLOBAL_EVENTS_END);
     198             : 
     199             :         stats_global_time_take(STATS_GLOBAL_FINI_START);
     200             :         log_log(LOG_INFO, "Finalizing simulation");
     201             :         serial_simulation_fini();
     202             : }
     203             : 
     204           0 : lp_id_t lp_id_get(void)
     205             : {
     206             :         return s_current_lp - s_lps;
     207             : }
     208             : 
     209           0 : struct lib_ctx *lib_ctx_get(void)
     210             : {
     211             :         return &s_current_lp->lib_ctx;
     212             : }

Generated by: LCOV version 1.14