model-net-lp.c 9.05 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
/*
 * Copyright (C) 2014 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

#include <stddef.h>
#include <assert.h>
#include "codes/model-net.h"
#include "codes/model-net-method.h"
#include "codes/model-net-lp.h"
12
#include "codes/model-net-sched.h"
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "codes/codes_mapping.h"
#include "codes/jenkins-hash.h"

#define MN_NAME "model_net_base"

/**** BEGIN SIMULATION DATA STRUCTURES ****/

int model_net_base_magic;

// message-type specific offsets - don't want to get bitten later by alignment
// issues...
static int msg_offsets[MAX_NETS];

typedef struct model_net_base_state {
    int net_id;
28
29
30
31
    // whether scheduler loop is running
    int in_sched_loop;
    // model-net scheduler
    model_net_sched *sched;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    // lp type and state of underlying model net method - cache here so we
    // don't have to constantly look up
    const tw_lptype *sub_type;
    void *sub_state;
} model_net_base_state;

/**** END SIMULATION DATA STRUCTURES ****/

/**** BEGIN LP, EVENT PROCESSING FUNCTION DECLS ****/

/* ROSS LP processing functions */  
static void model_net_base_lp_init(
        model_net_base_state * ns,
        tw_lp * lp);
static void model_net_base_event(
        model_net_base_state * ns,
        tw_bf * b,
        model_net_wrap_msg * m,
        tw_lp * lp);
static void model_net_base_event_rc(
        model_net_base_state * ns,
        tw_bf * b,
        model_net_wrap_msg * m,
        tw_lp * lp);
static void model_net_base_finalize(
        model_net_base_state * ns,
        tw_lp * lp);

/* event type handlers */
static void handle_new_msg(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp);
static void handle_sched_next(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp);
static void handle_new_msg_rc(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp);
static void handle_sched_next_rc(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp);

/* ROSS function pointer table for this LP */
tw_lptype model_net_base_lp = {
     (init_f) model_net_base_lp_init,
     (event_f) model_net_base_event,
     (revent_f) model_net_base_event_rc,
     (final_f)  model_net_base_finalize, 
     (map_f) codes_mapping,
     sizeof(model_net_base_state),
};

/**** END LP, EVENT PROCESSING FUNCTION DECLS ****/

/**** BEGIN IMPLEMENTATIONS ****/

void model_net_base_init(){
    uint32_t h1=0, h2=0;

    bj_hashlittle2(MN_NAME, strlen(MN_NAME), &h1, &h2);
    model_net_base_magic = h1+h2;

    // here, we initialize ALL lp types to use the base type
    // TODO: only initialize ones that are actually used
    for (int i = 0; i < MAX_NETS; i++){
        lp_type_register(model_net_lp_config_names[i], &model_net_base_lp);
    }

    // initialize the msg-specific offsets
    msg_offsets[SIMPLENET] = offsetof(model_net_wrap_msg, msg.m_snet);
    msg_offsets[SIMPLEWAN] = offsetof(model_net_wrap_msg, msg.m_swan);
    msg_offsets[TORUS] = offsetof(model_net_wrap_msg, msg.m_torus);
    msg_offsets[DRAGONFLY] = offsetof(model_net_wrap_msg, msg.m_dfly);
    msg_offsets[LOGGP] = offsetof(model_net_wrap_msg, msg.m_loggp);
}

void model_net_base_lp_init(
        model_net_base_state * ns,
        tw_lp * lp){
    // obtain the underlying lp type through codes-mapping
    char grp_name[MAX_NAME_LENGTH], lp_type_name[MAX_NAME_LENGTH];
    int grp_id, lp_type_id, grp_rep_id, offset;

    codes_mapping_get_lp_info(lp->gid, grp_name, &grp_id, &lp_type_id,
            lp_type_name, &grp_rep_id, &offset);

    // find the corresponding method name / index
    for (int i = 0; i < MAX_NETS; i++){
        if (strcmp(model_net_lp_config_names[i], lp_type_name) == 0){
            ns->net_id = i;
            break;
        }
    }

134
135
    // TODO: parameterize scheduler type
    ns->sched = malloc(sizeof(model_net_sched));
136
    model_net_sched_init(mn_sched_type, method_array[ns->net_id], ns->sched);
137

138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    ns->sub_type = model_net_get_lp_type(ns->net_id);
    // NOTE: some models actually expect LP state to be 0 initialized...
    // *cough anything that uses mn_stats_array cough*
    ns->sub_state = calloc(1, ns->sub_type->state_sz);

    // initialize the model-net method
    ns->sub_type->init(ns->sub_state, lp);
}

void model_net_base_event(
        model_net_base_state * ns,
        tw_bf * b,
        model_net_wrap_msg * m,
        tw_lp * lp){
    assert(m->magic == model_net_base_magic);
    
    switch (m->event_type){
        case MN_BASE_NEW_MSG:
            handle_new_msg(ns, b, m, lp);
            break;
        case MN_BASE_SCHED_NEXT:
            handle_sched_next(ns, b, m, lp);
            break;
        case MN_BASE_PASS: ;
            void * sub_msg = ((char*)m)+msg_offsets[ns->net_id];
            ns->sub_type->event(ns->sub_state, b, sub_msg, lp);
            break;
        /* ... */
        default:
            assert(!"model_net_base event type not known");
            break;
    }
}

void model_net_base_event_rc(
        model_net_base_state * ns,
        tw_bf * b,
        model_net_wrap_msg * m,
        tw_lp * lp){
    assert(m->magic == model_net_base_magic);
    
    switch (m->event_type){
        case MN_BASE_NEW_MSG:
            handle_new_msg_rc(ns, b, m, lp);
            break;
        case MN_BASE_SCHED_NEXT:
            handle_sched_next_rc(ns, b, m, lp);
            break;
        case MN_BASE_PASS: ;
            void * sub_msg = ((char*)m)+msg_offsets[ns->net_id];
            ns->sub_type->revent(ns->sub_state, b, sub_msg, lp);
            break;
        /* ... */
        default:
            assert(!"model_net_base event type not known");
            break;
    }
}

void model_net_base_finalize(
        model_net_base_state * ns,
        tw_lp * lp){
    ns->sub_type->final(ns->sub_state, lp);
    free(ns->sub_state);
}

204
205
/// bitfields used:
/// c0 - we initiated a sched_next event
206
207
208
209
210
void handle_new_msg(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp){
211
    // simply pass down to the scheduler
212
    model_net_request *r = &m->msg.m_base.u.req;
213
214
    void * m_data = m+1;
    void *remote = NULL, *local = NULL;
215
    if (r->remote_event_size > 0){
216
217
        remote = m_data;
        m_data = (char*)m_data + r->remote_event_size;
218
219
    }
    if (r->self_event_size > 0){
220
        local = m_data;
221
    }
222
223
224
225
226
227
    
    model_net_sched_add(r, r->remote_event_size, remote, r->self_event_size,
            local, ns->sched, &m->msg.m_base.rc, lp);
    
    if (ns->in_sched_loop == 0){
        b->c0 = 1;
228
        tw_event *e = codes_event_new(lp->gid, codes_local_latency(lp), lp);
229
230
231
232
233
234
        model_net_wrap_msg *m = tw_event_data(e);
        m->event_type = MN_BASE_SCHED_NEXT;
        m->magic = model_net_base_magic;
        // m_base not used in sched event
        tw_event_send(e);
        ns->in_sched_loop = 1;
235
236
    }
}
237
238
239

void handle_new_msg_rc(
        model_net_base_state *ns,
240
        tw_bf *b,
241
242
243
244
245
246
247
        model_net_wrap_msg *m,
        tw_lp *lp){
    model_net_sched_add_rc(ns->sched, &m->msg.m_base.rc, lp);
    if (b->c0){
        codes_local_latency_reverse(lp);
        ns->in_sched_loop = 0;
    }
248
}
249
250
251
252

/// bitfields used
/// c0 - scheduler loop is finished
void handle_sched_next(
253
254
255
256
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp){
257
    tw_stime poffset;
Jonathan Jenkins's avatar
Jonathan Jenkins committed
258
259
    int ret = model_net_sched_next(&poffset, ns->sched, m+1, 
            &m->msg.m_base.rc, lp);
260
261
262
263
264
265
266
267
    // we only need to know whether scheduling is finished or not - if not,
    // go to the 'next iteration' of the loop
    if (ret == -1){
        b->c0 = 1;
        ns->in_sched_loop = 0;
    }
    else {
        tw_event *e = codes_event_new(lp->gid, 
268
                poffset+codes_local_latency(lp), lp);
269
270
271
272
273
        model_net_wrap_msg *m = tw_event_data(e);
        m->event_type = MN_BASE_SCHED_NEXT;
        m->magic = model_net_base_magic;
        // no need to set m_base here
        tw_event_send(e);
274
275
    }
}
276

277
278
279
280
281
void handle_sched_next_rc(
        model_net_base_state * ns,
        tw_bf *b,
        model_net_wrap_msg * m,
        tw_lp * lp){
Jonathan Jenkins's avatar
Jonathan Jenkins committed
282
    model_net_sched_next_rc(ns->sched, m+1, &m->msg.m_base.rc, lp);
283
284
285
286
287
288
289

    if (b->c0){
        ns->in_sched_loop = 1;
    }
    else{
        codes_local_latency_reverse(lp);
    }
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
}

/**** END IMPLEMENTATIONS ****/

tw_event * model_net_method_event_new(
        tw_lpid dest_gid,
        tw_stime offset_ts,
        tw_lp *sender,
        int net_id,
        void **msg_data,
        void **extra_data){
    tw_event *e = tw_event_new(dest_gid, offset_ts, sender);
    model_net_wrap_msg *m_wrap = tw_event_data(e);
    m_wrap->event_type = MN_BASE_PASS;
    m_wrap->magic = model_net_base_magic;
    *msg_data = ((char*)m_wrap)+msg_offsets[net_id];
    // extra_data is optional
    if (extra_data != NULL){
        *extra_data = m_wrap + 1;
    }
    return e;
}

void * model_net_method_get_edata(int net_id, void *msg){
    return (char*)msg + sizeof(model_net_wrap_msg) - msg_offsets[net_id];
}

/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 *
 * vim: ft=c ts=8 sts=4 sw=4 expandtab
 */