119 lines
2.5 KiB
C
119 lines
2.5 KiB
C
#include "model_thread.h"
|
|
|
|
#include "model_pvt.h"
|
|
|
|
static int
|
|
init_chan(struct model_thread *th, const struct model_chan_spec *spec, int64_t gindex)
|
|
{
|
|
const char *fmt = "%s.thread%ld.%s";
|
|
const char *prefix = spec->prefix;
|
|
|
|
th->ch = calloc(spec->nch, sizeof(struct chan));
|
|
if (th->ch == NULL) {
|
|
err("calloc failed:");
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < spec->nch; i++) {
|
|
struct chan *c = &th->ch[i];
|
|
int type = spec->ch_stack[i];
|
|
const char *ch_name = spec->ch_names[i];
|
|
chan_init(c, type, fmt, prefix, gindex, ch_name);
|
|
|
|
if (spec->ch_dup != NULL) {
|
|
int dup = spec->ch_dup[i];
|
|
chan_prop_set(c, CHAN_DUPLICATES, dup);
|
|
}
|
|
|
|
if (bay_register(th->bay, c) != 0) {
|
|
err("bay_register failed");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
th->track = calloc(spec->nch, sizeof(struct track));
|
|
if (th->track == NULL) {
|
|
err("calloc failed:");
|
|
return -1;
|
|
}
|
|
|
|
for (int i = 0; i < spec->nch; i++) {
|
|
struct track *track = &th->track[i];
|
|
|
|
const char *ch_name = spec->ch_names[i];
|
|
int track_mode = spec->track[i];
|
|
|
|
if (track_init(track, th->bay, TRACK_TYPE_TH,
|
|
track_mode, fmt,
|
|
prefix, gindex, ch_name) != 0) {
|
|
err("track_init failed");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
init_thread(struct thread *systh, struct bay *bay, const struct model_thread_spec *spec)
|
|
{
|
|
struct model_thread *th = calloc(1, spec->size);
|
|
if (th == NULL) {
|
|
err("calloc failed:");
|
|
return -1;
|
|
}
|
|
|
|
th->spec = spec;
|
|
th->bay = bay;
|
|
|
|
if (init_chan(th, spec->chan, systh->gindex) != 0) {
|
|
err("init_chan failed");
|
|
return -1;
|
|
}
|
|
|
|
extend_set(&systh->ext, spec->model->model, th);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
model_thread_create(struct emu *emu, const struct model_thread_spec *spec)
|
|
{
|
|
struct system *sys = &emu->system;
|
|
struct bay *bay = &emu->bay;
|
|
|
|
for (struct thread *t = sys->threads; t; t = t->gnext) {
|
|
if (init_thread(t, bay, spec) != 0) {
|
|
err("init_thread failed");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
model_thread_connect(struct emu *emu, const struct model_thread_spec *spec)
|
|
{
|
|
int id = spec->model->model;
|
|
struct system *sys = &emu->system;
|
|
|
|
for (struct thread *t = sys->threads; t; t = t->gnext) {
|
|
struct model_thread *th = EXT(t, id);
|
|
struct chan *sel = &t->chan[TH_CHAN_STATE];
|
|
int nch = th->spec->chan->nch;
|
|
if (track_connect_thread(th->track, th->ch, sel, nch) != 0) {
|
|
err("track_thread failed");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Connect channels to Paraver trace */
|
|
if (model_pvt_connect_thread(emu, spec) != 0) {
|
|
err("model_pvt_connect_thread failed");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|