~arcachofo/simulide/1.1.0

« back to all changes in this revision

Viewing changes to src/simavr/sim/sim_cycle_timers.c

  • Committer: arcachofo
  • Date: 2021-01-01 14:23:42 UTC
  • Revision ID: arcachofo@simulide.com-20210101142342-ozfljnll44g5lbl3
Initial Commit 0.5.15-RC3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
        sim_cycle_timers.c
 
3
 
 
4
        Copyright 2008-2012 Michel Pollet <buserror@gmail.com>
 
5
 
 
6
        This file is part of simavr.
 
7
 
 
8
        simavr is free software: you can redistribute it and/or modify
 
9
        it under the terms of the GNU General Public License as published by
 
10
        the Free Software Foundation, either version 3 of the License, or
 
11
        (at your option) any later version.
 
12
 
 
13
        simavr is distributed in the hope that it will be useful,
 
14
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
        GNU General Public License for more details.
 
17
 
 
18
        You should have received a copy of the GNU General Public License
 
19
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
 
20
 */
 
21
 
 
22
#include <stdlib.h>
 
23
#include <stdio.h>
 
24
#include <string.h>
 
25
#include "sim_avr.h"
 
26
#include "sim_time.h"
 
27
#include "sim_cycle_timers.h"
 
28
 
 
29
#define QUEUE(__q, __e) { \
 
30
        (__e)->next =( __q); \
 
31
                (__q) = __e; \
 
32
        }
 
33
#define DETACH(__q, __l, __e) { \
 
34
        if( __l) \
 
35
            (__l)->next =( __e)->next; \
 
36
                else \
 
37
            (__q) =( __e)->next; \
 
38
        }
 
39
#define INSERT(__q, __l, __e) { \
 
40
        if( __l) { \
 
41
            (__e)->next =( __l)->next; \
 
42
            (__l)->next =( __e); \
 
43
                } else { \
 
44
            (__e)->next =( __q); \
 
45
            (__q) =( __e); \
 
46
                } \
 
47
        }
 
48
 
 
49
#define DEFAULT_SLEEP_CYCLES 1000
 
50
 
 
51
void avr_cycle_timer_reset( struct avr_t * avr )
 
52
{
 
53
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
54
    memset( pool, 0, sizeof(*pool) );
 
55
 
 
56
    for( int i = 0; i < MAX_CYCLE_TIMERS; i++ ) // queue all slots into the free queue
 
57
    {
 
58
        avr_cycle_timer_slot_p t = &pool->t_slots[i];
 
59
        QUEUE( pool->slot_free, t );
 
60
        }
 
61
    ////avr->run_cycle_count = 1;
 
62
    ////avr->run_cycle_limit = 1;
 
63
}
 
64
 
 
65
////
 
66
/*static avr_cycle_count_t
 
67
avr_cycle_timer_return_sleep_run_cycles_limited(
 
68
        avr_t *avr,
 
69
        avr_cycle_count_t sleep_cycle_count)
 
70
{
 
71
        // run_cycle_count is bound to run_cycle_limit but NOT less than 1 cycle...
 
72
        //      this is not an error!..  unless you like deadlock.
 
73
    avr_cycle_count_t run_cycle_count =( (avr->run_cycle_limit >= sleep_cycle_count) ?
 
74
                sleep_cycle_count : avr->run_cycle_limit);
 
75
 
 
76
        avr->run_cycle_count = run_cycle_count ? run_cycle_count : 1;
 
77
 
 
78
        // sleep cycles are returned unbounded thus preserving original behavior.
 
79
        return(sleep_cycle_count);
 
80
}*/
 
81
 
 
82
/*static void avr_cycle_timer_reset_sleep_run_cycles_limited( avr_t *avr )
 
83
{
 
84
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
85
        avr_cycle_count_t sleep_cycle_count = DEFAULT_SLEEP_CYCLES;
 
86
 
 
87
    if( pool->timer )
 
88
    {
 
89
        if( pool->timer->when > avr->cycle ) sleep_cycle_count = pool->timer->when - avr->cycle;
 
90
        else sleep_cycle_count = 0;
 
91
        }
 
92
    ////avr_cycle_timer_return_sleep_run_cycles_limited( avr, sleep_cycle_count );
 
93
}*/
 
94
 
 
95
// no sanity checks checking here, on purpose
 
96
static void avr_cycle_timer_insert(
 
97
                avr_t * avr,
 
98
                avr_cycle_count_t when,
 
99
        avr_cycle_timer_t event,
 
100
                void * param)
 
101
{
 
102
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
103
 
 
104
    when += avr->cycle;
 
105
 
 
106
    avr_cycle_timer_slot_p slot = pool->slot_free;
 
107
 
 
108
    if( !slot) {
 
109
        AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: ran out of timers( %d)!\n", __func__, MAX_CYCLE_TIMERS);
 
110
                return;
 
111
    }
 
112
        // detach head
 
113
    pool->slot_free = slot->next;
 
114
    slot->next = NULL;
 
115
    slot->event = event;
 
116
    slot->param = param;
 
117
    slot->when = when;
 
118
 
 
119
    // find its place in the list
 
120
    avr_cycle_timer_slot_p loop = pool->t_slot, last = NULL;
 
121
    while( loop )
 
122
    {
 
123
        if( loop->when > when ) break;
 
124
 
 
125
        last = loop;
 
126
        loop = loop->next;
 
127
    }
 
128
    INSERT( pool->t_slot, last, slot );
 
129
}
 
130
 
 
131
void avr_cycle_timer_register( avr_t * avr, avr_cycle_count_t when, avr_cycle_timer_t timer, void* param)
 
132
{
 
133
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
134
 
 
135
    avr_cycle_timer_cancel( avr, timer, param ); // remove it if it was already scheduled
 
136
 
 
137
    if( !pool->slot_free )
 
138
    {
 
139
        AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: pool is full( %d)!\n", __func__, MAX_CYCLE_TIMERS);
 
140
                return;
 
141
        }
 
142
    avr_cycle_timer_insert( avr, when, timer, param );
 
143
    ////avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
 
144
}
 
145
 
 
146
void avr_cycle_timer_register_usec( avr_t* avr, uint32_t when, avr_cycle_timer_t timer, void* param)
 
147
{
 
148
    avr_cycle_timer_register( avr, avr_usec_to_cycles(avr, when), timer, param);
 
149
}
 
150
 
 
151
void avr_cycle_timer_cancel( avr_t* avr, avr_cycle_timer_t event, void* param)
 
152
{
 
153
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
154
 
 
155
        // find its place in the list
 
156
    avr_cycle_timer_slot_p t = pool->t_slot, last = NULL;
 
157
    while( t)
 
158
    {
 
159
        if( t->event == event && t->param == param)
 
160
        {
 
161
            DETACH(pool->t_slot, last, t);
 
162
            QUEUE(pool->slot_free, t);
 
163
                        break;
 
164
                }
 
165
                last = t;
 
166
                t = t->next;
 
167
        }
 
168
    ////avr_cycle_timer_reset_sleep_run_cycles_limited(avr);
 
169
}
 
170
 
 
171
/*
 
172
 * Check to see if a timer is present, if so, return the number( +1) of
 
173
 * cycles left for it to fire, and if not present, return zero
 
174
 */
 
175
avr_cycle_count_t
 
176
avr_cycle_timer_status(
 
177
                avr_t * avr,
 
178
        avr_cycle_timer_t event,
 
179
                void * param)
 
180
{
 
181
        avr_cycle_timer_pool_t * pool = &avr->cycle_timers;
 
182
 
 
183
        // find its place in the list
 
184
    avr_cycle_timer_slot_p t = pool->t_slot;
 
185
    while( t)
 
186
    {
 
187
        if( t->event == event && t->param == param)
 
188
        {
 
189
            return 1 +( t->when - avr->cycle);
 
190
                }
 
191
                t = t->next;
 
192
        }
 
193
        return 0;
 
194
}
 
195
 
 
196
/*
 
197
 * run through all the timers, call the ones that needs it,
 
198
 * clear the ones that wants it, and calculate the next
 
199
 * potential cycle we could sleep for...
 
200
 */
 
201
avr_cycle_count_t avr_cycle_timer_process( avr_t* avr )
 
202
{
 
203
    avr_cycle_timer_pool_t* pool = &avr->cycle_timers;
 
204
 
 
205
    if( pool->t_slot)
 
206
    do
 
207
    {
 
208
        avr_cycle_timer_slot_p slot = pool->t_slot;
 
209
        avr_cycle_count_t when = slot->when;
 
210
 
 
211
        if( when > avr->cycle)
 
212
            return 0; ////avr_cycle_timer_return_sleep_run_cycles_limited( avr, when-avr->cycle);
 
213
 
 
214
                // detach from active timers
 
215
        pool->t_slot = slot->next;
 
216
        slot->next = NULL;
 
217
        do
 
218
        {
 
219
            avr_cycle_count_t w = slot->event( avr, when, slot->param );
 
220
                        // make sure the return value is either zero, or greater
 
221
                        // than the last one to prevent infinite loop here
 
222
                        when = w > when ? w : 0;
 
223
        } while( when && when <= avr->cycle );
 
224
                
 
225
        if( when ) // reschedule then
 
226
            avr_cycle_timer_insert( avr, when-avr->cycle, slot->event, slot->param );
 
227
 
 
228
        QUEUE( pool->slot_free, slot ); // requeue this one into the free ones
 
229
    }
 
230
    while( pool->t_slot);
 
231
 
 
232
        // original behavior was to return 1000 cycles when no timers were present...
 
233
        // run_cycles are bound to at least one cycle but no more than requested limit...
 
234
        //      value passed here is returned unbounded, thus preserving original behavior.
 
235
    return 0;///avr_cycle_timer_return_sleep_run_cycles_limited(avr, DEFAULT_SLEEP_CYCLES);
 
236
}