diff --git a/src/emu/CMakeLists.txt b/src/emu/CMakeLists.txt index b3f2344..8352a24 100644 --- a/src/emu/CMakeLists.txt +++ b/src/emu/CMakeLists.txt @@ -47,12 +47,8 @@ add_library(emu STATIC nanos6/event.c nosv/setup.c nosv/event.c - nodes/probe.c - nodes/connect.c - nodes/create.c + nodes/setup.c nodes/event.c - nodes/pvt.c - nodes/finish.c ) add_executable(ovniemu ovniemu.c) diff --git a/src/emu/nodes/connect.c b/src/emu/nodes/connect.c deleted file mode 100644 index 8d2cf6d..0000000 --- a/src/emu/nodes/connect.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "nodes_priv.h" - -static const int th_track[CH_MAX] = { - [CH_SUBSYSTEM] = TRACK_TH_RUN, /* FIXME: Why not active? */ -}; - -static const int cpu_track[CH_MAX] = { - [CH_SUBSYSTEM] = TRACK_TH_RUN, -}; - -int -nodes_get_track(int c, int type) -{ - if (type == CT_TH) - return th_track[c]; - else - return cpu_track[c]; -} - -static int -connect_cpu(struct emu *emu, struct cpu *scpu) -{ - struct nodes_cpu *cpu = EXT(scpu, 'D'); - for (int i = 0; i < CH_MAX; i++) { - struct track *track = &cpu->track[i]; - - /* Choose select CPU channel based on tracking mode (only - * TRACK_TH_RUN allowed, as active may cause collisions) */ - int mode = nodes_get_track(i, CT_CPU); - struct chan *sel = cpu_get_th_chan(scpu, mode); - if (track_set_select(track, mode, sel, NULL) != 0) { - err("track_select failed"); - return -1; - } - - /* Add each thread as input */ - for (struct thread *t = emu->system.threads; t; t = t->gnext) { - struct nodes_thread *th = EXT(t, 'D'); - - /* Choose input channel from the thread output channels - * based on CPU tracking mode */ - struct value key = value_int64(t->gindex); - struct chan *inp = track_get_output(&th->track[i], mode); - - if (track_add_input(track, mode, key, inp) != 0) { - err("track_add_input failed"); - return -1; - } - } - - /* Set the PRV output */ - track_set_default(track, nodes_get_track(i, CT_CPU)); - } - - return 0; -} - -int -nodes_connect(struct emu *emu) -{ - struct system *sys = &emu->system; - - /* threads */ - for (struct thread *t = sys->threads; t; t = t->gnext) { - struct nodes_thread *th = EXT(t, 'D'); - struct chan *sel = &t->chan[TH_CHAN_STATE]; - if (track_connect_thread(th->track, th->ch, th_track, sel, CH_MAX) != 0) { - err("track_thread failed"); - return -1; - } - } - - /* cpus */ - for (struct cpu *c = sys->cpus; c; c = c->next) { - if (connect_cpu(emu, c) != 0) { - err("connect_cpu failed"); - return -1; - } - } - - if (nodes_init_pvt(emu) != 0) { - err("init_pvt failed"); - return -1; - } - - return 0; -} diff --git a/src/emu/nodes/create.c b/src/emu/nodes/create.c deleted file mode 100644 index 24b2a48..0000000 --- a/src/emu/nodes/create.c +++ /dev/null @@ -1,126 +0,0 @@ -#include "nodes_priv.h" - -static const char *chan_name[CH_MAX] = { - [CH_SUBSYSTEM] = "subsystem", -}; - -static const int chan_stack[CH_MAX] = { - [CH_SUBSYSTEM] = 1, -}; - -static int -init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex) -{ - for (int i = 0; i < CH_MAX; i++) { - struct chan *c = &chans[i]; - int type = chan_stack[i]; - chan_init(c, type, fmt, gindex, chan_name[i]); - - if (bay_register(bay, c) != 0) { - err("bay_register failed"); - return -1; - } - } - - return 0; -} - -static int -init_tracks(struct bay *bay, struct track *tracks, const char *fmt, int64_t gindex) -{ - for (int i = 0; i < CH_MAX; i++) { - struct track *track = &tracks[i]; - - if (track_init(track, bay, TRACK_TYPE_TH, fmt, gindex, chan_name[i]) != 0) { - err("track_init failed"); - return -1; - } - } - - return 0; -} - -static int -init_cpu(struct bay *bay, struct cpu *syscpu) -{ - struct nodes_cpu *cpu = calloc(1, sizeof(struct nodes_cpu)); - if (cpu == NULL) { - err("calloc failed:"); - return -1; - } - - cpu->track = calloc(CH_MAX, sizeof(struct track)); - if (cpu->track == NULL) { - err("calloc failed:"); - return -1; - } - - char *fmt = "nodes.cpu%ld.%s"; - if (init_tracks(bay, cpu->track, fmt, syscpu->gindex) != 0) { - err("init_chans failed"); - return -1; - } - - extend_set(&syscpu->ext, 'D', cpu); - return 0; -} - -static int -init_thread(struct bay *bay, struct thread *systh) -{ - struct nodes_thread *th = calloc(1, sizeof(struct nodes_thread)); - if (th == NULL) { - err("calloc failed:"); - return -1; - } - - th->ch = calloc(CH_MAX, sizeof(struct chan)); - if (th->ch == NULL) { - err("calloc failed:"); - return -1; - } - - th->track = calloc(CH_MAX, sizeof(struct track)); - if (th->track == NULL) { - err("calloc failed:"); - return -1; - } - - char *fmt = "nodes.thread%ld.%s"; - if (init_chans(bay, th->ch, fmt, systh->gindex) != 0) { - err("init_chans failed"); - return -1; - } - - if (init_tracks(bay, th->track, fmt, systh->gindex) != 0) { - err("init_tracks failed"); - return -1; - } - - extend_set(&systh->ext, 'D', th); - - return 0; -} - -int -nodes_create(struct emu *emu) -{ - struct system *sys = &emu->system; - struct bay *bay = &emu->bay; - - for (struct cpu *c = sys->cpus; c; c = c->next) { - if (init_cpu(bay, c) != 0) { - err("init_cpu failed"); - return -1; - } - } - - for (struct thread *t = sys->threads; t; t = t->gnext) { - if (init_thread(bay, t) != 0) { - err("init_thread failed"); - return -1; - } - } - - return 0; -} diff --git a/src/emu/nodes/event.c b/src/emu/nodes/event.c index da0ebb6..d545f62 100644 --- a/src/emu/nodes/event.c +++ b/src/emu/nodes/event.c @@ -48,7 +48,7 @@ simple(struct emu *emu) int st = entry[2]; struct nodes_thread *th = EXT(emu->thread, 'D'); - struct chan *ch = &th->ch[chind]; + struct chan *ch = &th->m.ch[chind]; if (action == PUSH) { return chan_push(ch, value_int64(st)); diff --git a/src/emu/nodes/finish.c b/src/emu/nodes/finish.c deleted file mode 100644 index c11b500..0000000 --- a/src/emu/nodes/finish.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "nodes_priv.h" - -static int -end_lint(struct emu *emu) -{ - struct system *sys = &emu->system; - - /* Ensure we run out of subsystem states */ - for (struct thread *t = sys->threads; t; t = t->gnext) { - struct nodes_thread *th = EXT(t, 'D'); - struct chan *ch = &th->ch[CH_SUBSYSTEM]; - int stacked = ch->data.stack.n; - if (stacked > 0) { - struct value top; - if (chan_read(ch, &top) != 0) { - err("chan_read failed for subsystem"); - return -1; - } - - err("thread %d ended with %d stacked nodes subsystems, top=\"%s\"\n", - t->tid, stacked, nodes_ss_name(top.i)); - return -1; - } - } - - return 0; -} - -int -nodes_finish(struct emu *emu) -{ - if (nodes_finish_pvt(emu) != 0) { - err("finish_pvt failed"); - return -1; - } - - /* When running in linter mode perform additional checks */ - if (emu->args.linter_mode && end_lint(emu) != 0) { - err("end_lint failed"); - return -1; - } - - return 0; -} diff --git a/src/emu/nodes/nodes_priv.h b/src/emu/nodes/nodes_priv.h index 3ba59fb..3f50e82 100644 --- a/src/emu/nodes/nodes_priv.h +++ b/src/emu/nodes/nodes_priv.h @@ -5,18 +5,11 @@ #define NODES_PRIV_H #include "emu.h" -#include "chan.h" -#include "mux.h" -#include "task.h" +#include "model_cpu.h" +#include "model_thread.h" /* Private enums */ -enum nodes_chan_type { - CT_TH = 0, - CT_CPU, - CT_MAX -}; - enum nodes_chan { CH_SUBSYSTEM = 0, CH_MAX, @@ -34,12 +27,11 @@ enum nodes_ss_values { }; struct nodes_thread { - struct chan *ch; - struct track *track; + struct model_thread m; }; struct nodes_cpu { - struct track *track; + struct model_cpu m; }; int nodes_probe(struct emu *emu); @@ -48,9 +40,4 @@ int nodes_connect(struct emu *emu); int nodes_event(struct emu *emu); int nodes_finish(struct emu *emu); -int nodes_init_pvt(struct emu *emu); -int nodes_finish_pvt(struct emu *emu); -const char *nodes_ss_name(int ss); -int nodes_get_track(int c, int type); - #endif /* NODES_PRIV_H */ diff --git a/src/emu/nodes/probe.c b/src/emu/nodes/probe.c deleted file mode 100644 index 2a48780..0000000 --- a/src/emu/nodes/probe.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "nodes_priv.h" - -struct model_spec model_nodes = { - .name = "nodes", - .model = 'D', - .create = nodes_create, - .connect = nodes_connect, - .event = nodes_event, - .probe = nodes_probe, - .finish = nodes_finish, -}; - -int -nodes_probe(struct emu *emu) -{ - if (emu->system.nthreads == 0) - return 1; - - return 0; -} diff --git a/src/emu/nodes/pvt.c b/src/emu/nodes/pvt.c deleted file mode 100644 index 88cc04b..0000000 --- a/src/emu/nodes/pvt.c +++ /dev/null @@ -1,228 +0,0 @@ -#include "nodes_priv.h" - -/* TODO: Assign types on runtime and generate configs */ - -static const int pvt_type[] = { - [CH_SUBSYSTEM] = 30, -}; - -static const char *pcf_prefix[CH_MAX] = { - [CH_SUBSYSTEM] = "NODES subsystem", -}; - -static const char *pcf_suffix[TRACK_TH_MAX] = { - [TRACK_TH_ANY] = "", - [TRACK_TH_RUN] = "of the RUNNING thread", - [TRACK_TH_ACT] = "of the ACTIVE thread", -}; - -static const struct pcf_value_label nodes_ss_values[] = { - { ST_REGISTER, "Dependencies: Registering task accesses" }, - { ST_UNREGISTER, "Dependencies: Unregistering task accesses" }, - { ST_IF0_WAIT, "If0: Waiting for an If0 task" }, - { ST_IF0_INLINE, "If0: Executing an If0 task inline" }, - { ST_TASKWAIT, "Taskwait: Taskwait" }, - { ST_CREATE, "Add Task: Creating a task" }, - { ST_SUBMIT, "Add Task: Submitting a task" }, - { ST_SPAWN, "Spawn Function: Spawning a function" }, - { -1, NULL }, -}; - -static const struct pcf_value_label (*pcf_chan_value_labels[CH_MAX])[] = { - [CH_SUBSYSTEM] = &nodes_ss_values, -}; - -/* ------------------------------ pcf ------------------------------ */ - -static int -create_values(struct pcf_type *t, int c) -{ - const struct pcf_value_label(*q)[] = pcf_chan_value_labels[c]; - - if (q == NULL) - return 0; - - for (const struct pcf_value_label *p = *q; p->label != NULL; p++) - pcf_add_value(t, p->value, p->label); - - return 0; -} - -static int -create_type(struct pcf *pcf, enum nodes_chan c, enum nodes_chan_type ct) -{ - long type = pvt_type[c]; - - if (type == -1) - return 0; - - /* Compute the label by joining the two parts */ - const char *prefix = pcf_prefix[c]; - int track_mode = nodes_get_track(c, ct); - const char *suffix = pcf_suffix[track_mode]; - - char label[MAX_PCF_LABEL]; - int ret = snprintf(label, MAX_PCF_LABEL, "%s %s", - prefix, suffix); - - if (ret >= MAX_PCF_LABEL) { - err("computed type label too long"); - return -1; - } - - struct pcf_type *pcftype = pcf_add_type(pcf, type, label); - - return create_values(pcftype, c); -} - -static int -init_pcf(struct pcf *pcf, enum nodes_chan_type ct) -{ - /* Create default types and values */ - for (enum nodes_chan c = 0; c < CH_MAX; c++) { - if (create_type(pcf, c, ct) != 0) { - err("create_type failed"); - return -1; - } - } - - return 0; -} - -/* ------------------------------ prv ------------------------------ */ - -static int -connect_thread_prv(struct emu *emu, struct thread *thread, struct prv *prv) -{ - struct nodes_thread *th = EXT(thread, 'D'); - for (int i = 0; i < CH_MAX; i++) { - struct chan *out = track_get_default(&th->track[i]); - long type = pvt_type[i]; - long row = thread->gindex; - if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { - err("prv_register failed"); - return -1; - } - } - - return 0; -} - -static int -connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv) -{ - struct nodes_cpu *cpu = EXT(scpu, 'D'); - for (int i = 0; i < CH_MAX; i++) { - struct chan *out = track_get_default(&cpu->track[i]); - long type = pvt_type[i]; - long row = scpu->gindex; - if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { - err("prv_register failed"); - return -1; - } - } - - return 0; -} - -static int -connect_threads(struct emu *emu) -{ - struct system *sys = &emu->system; - - /* Get thread PRV */ - struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread"); - if (pvt == NULL) { - err("cannot find thread pvt"); - return -1; - } - - /* Connect thread channels to PRV */ - struct prv *prv = pvt_get_prv(pvt); - for (struct thread *t = sys->threads; t; t = t->gnext) { - if (connect_thread_prv(emu, t, prv) != 0) { - err("connect_thread_prv failed"); - return -1; - } - } - - /* Init thread PCF */ - struct pcf *pcf = pvt_get_pcf(pvt); - if (init_pcf(pcf, CT_TH) != 0) { - err("init_pcf failed"); - return -1; - } - - return 0; -} - -static int -connect_cpus(struct emu *emu) -{ - struct system *sys = &emu->system; - - /* Get cpu PRV */ - struct pvt *pvt = recorder_find_pvt(&emu->recorder, "cpu"); - if (pvt == NULL) { - err("cannot find cpu pvt"); - return -1; - } - - /* Connect CPU channels to PRV */ - struct prv *prv = pvt_get_prv(pvt); - for (struct cpu *c = sys->cpus; c; c = c->next) { - if (connect_cpu_prv(emu, c, prv) != 0) { - err("connect_cpu_prv failed"); - return -1; - } - } - - /* Init CPU PCF */ - struct pcf *pcf = pvt_get_pcf(pvt); - if (init_pcf(pcf, CT_CPU) != 0) { - err("init_pcf failed"); - return -1; - } - - return 0; -} - -/* Connect all outputs to the paraver trace and setup PCF types */ -int -nodes_init_pvt(struct emu *emu) -{ - if (connect_threads(emu) != 0) { - err("connect_threads failed"); - return -1; - } - - if (connect_cpus(emu) != 0) { - err("connect_cpus failed"); - return -1; - } - - return 0; -} - -int -nodes_finish_pvt(struct emu *emu) -{ - UNUSED(emu); - return 0; -} - -const char * -nodes_ss_name(int ss) -{ - static const char *unknown = "(unknown)"; - const char *name = unknown; - const struct pcf_value_label *pv; - for (pv = &nodes_ss_values[0]; pv->label; pv++) { - if (pv->value == ss) { - name = pv->label; - break; - } - } - - return name; -} diff --git a/src/emu/nodes/setup.c b/src/emu/nodes/setup.c new file mode 100644 index 0000000..063f6d0 --- /dev/null +++ b/src/emu/nodes/setup.c @@ -0,0 +1,181 @@ +#include "nodes_priv.h" + +static const char model_name[] = "nodes"; +static const int model_id = 'D'; + +struct model_spec model_nodes = { + .name = model_name, + .model = model_id, + .create = nodes_create, + .connect = nodes_connect, + .event = nodes_event, + .probe = nodes_probe, + .finish = nodes_finish, +}; + +/* ----------------- channels ------------------ */ + +static const char *chan_name[CH_MAX] = { + [CH_SUBSYSTEM] = "subsystem", +}; + +static const int chan_stack[CH_MAX] = { + [CH_SUBSYSTEM] = 1, +}; + +/* ----------------- pvt ------------------ */ + +static const int pvt_type[] = { + [CH_SUBSYSTEM] = 30, +}; + +static const char *pcf_prefix[CH_MAX] = { + [CH_SUBSYSTEM] = "NODES subsystem", +}; + +static const struct pcf_value_label nodes_ss_values[] = { + { ST_REGISTER, "Dependencies: Registering task accesses" }, + { ST_UNREGISTER, "Dependencies: Unregistering task accesses" }, + { ST_IF0_WAIT, "If0: Waiting for an If0 task" }, + { ST_IF0_INLINE, "If0: Executing an If0 task inline" }, + { ST_TASKWAIT, "Taskwait: Taskwait" }, + { ST_CREATE, "Add Task: Creating a task" }, + { ST_SUBMIT, "Add Task: Submitting a task" }, + { ST_SPAWN, "Spawn Function: Spawning a function" }, + { -1, NULL }, +}; + +static const struct pcf_value_label (*pcf_labels[CH_MAX])[] = { + [CH_SUBSYSTEM] = &nodes_ss_values, +}; + +static const struct model_pvt_spec pvt_spec = { + .type = pvt_type, + .prefix = pcf_prefix, + .label = pcf_labels, +}; + +/* ----------------- tracking ------------------ */ + +static const int th_track[CH_MAX] = { + [CH_SUBSYSTEM] = TRACK_TH_RUN, /* FIXME: Why not active? */ +}; + +static const int cpu_track[CH_MAX] = { + [CH_SUBSYSTEM] = TRACK_TH_RUN, +}; + +/* ----------------- chan_spec ------------------ */ + +static const struct model_chan_spec th_chan = { + .nch = CH_MAX, + .prefix = model_name, + .ch_names = chan_name, + .ch_stack = chan_stack, + .pvt = &pvt_spec, + .track = th_track, +}; + +static const struct model_chan_spec cpu_chan = { + .nch = CH_MAX, + .prefix = model_name, + .ch_names = chan_name, + .ch_stack = chan_stack, + .pvt = &pvt_spec, + .track = cpu_track, +}; + +/* ----------------- models ------------------ */ + +static const struct model_cpu_spec cpu_spec = { + .size = sizeof(struct nodes_cpu), + .chan = &cpu_chan, + .model = &model_nodes, +}; + +static const struct model_thread_spec th_spec = { + .size = sizeof(struct nodes_thread), + .chan = &th_chan, + .model = &model_nodes, +}; + +/* ----------------------------------------------------- */ + +int +nodes_probe(struct emu *emu) +{ + if (emu->system.nthreads == 0) + return 1; + + return 0; +} + +int +nodes_create(struct emu *emu) +{ + if (model_thread_create(emu, &th_spec) != 0) { + err("model_thread_init failed"); + return -1; + } + + if (model_cpu_create(emu, &cpu_spec) != 0) { + err("model_cpu_init failed"); + return -1; + } + + return 0; +} + +int +nodes_connect(struct emu *emu) +{ + if (model_thread_connect(emu, &th_spec) != 0) { + err("model_thread_connect failed"); + return -1; + } + + if (model_cpu_connect(emu, &cpu_spec) != 0) { + err("model_cpu_connect failed"); + return -1; + } + + return 0; +} + +static int +end_lint(struct emu *emu) +{ + struct system *sys = &emu->system; + + /* Ensure we run out of subsystem states */ + for (struct thread *t = sys->threads; t; t = t->gnext) { + struct nodes_thread *th = EXT(t, model_id); + struct chan *ch = &th->m.ch[CH_SUBSYSTEM]; + int stacked = ch->data.stack.n; + if (stacked > 0) { + struct value top; + if (chan_read(ch, &top) != 0) { + err("chan_read failed for subsystem"); + return -1; + } + + err("thread %d ended with %d stacked nodes subsystems", + t->tid, stacked); + return -1; + } + } + + return 0; +} + +int +nodes_finish(struct emu *emu) +{ + /* When running in linter mode perform additional checks */ + if (emu->args.linter_mode && end_lint(emu) != 0) { + err("end_lint failed"); + return -1; + } + + return 0; +}