ovni/src/emu/emu.c

204 lines
4.2 KiB
C

/* Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "emu.h"
#include <string.h>
#include "emu_ev.h"
#include "models.h"
#include "stream.h"
int
emu_init(struct emu *emu, int argc, char *argv[])
{
memset(emu, 0, sizeof(*emu));
emu_args_init(&emu->args, argc, argv);
/* Load the streams into the trace */
if (trace_load(&emu->trace, emu->args.tracedir) != 0) {
err("cannot load trace '%s'", emu->args.tracedir);
return -1;
}
/* Parse the trace and build the emu_system */
if (system_init(&emu->system, &emu->args, &emu->trace) != 0) {
err("cannot init system for trace '%s'",
emu->args.tracedir);
return -1;
}
/* Place output inside the same tracedir directory */
if (recorder_init(&emu->recorder, emu->args.tracedir) != 0) {
err("recorder_init failed");
return -1;
}
/* Initialize the bay */
bay_init(&emu->bay);
/* Connect system channels to bay */
if (system_connect(&emu->system, &emu->bay, &emu->recorder) != 0) {
err("system_connect failed");
return -1;
}
if (player_init(&emu->player, &emu->trace, 0) != 0) {
err("cannot init player for trace '%s'",
emu->args.tracedir);
return -1;
}
model_init(&emu->model);
/* Register all the models */
if (models_register(&emu->model) != 0) {
err("failed to register models");
return -1;
}
if (model_probe(&emu->model, emu) != 0) {
err("model_probe failed");
return -1;
}
if (model_create(&emu->model, emu) != 0) {
err("model_create failed");
return -1;
}
emu_stat_init(&emu->stat);
return 0;
}
int
emu_connect(struct emu *emu)
{
if (model_connect(&emu->model, emu) != 0) {
err("model_connect failed");
return -1;
}
/* Run a propagation phase so we clean all the dirty channels, in
* particular the select channel of the muxes */
if (bay_propagate(&emu->bay) != 0) {
err("bay_propagate failed");
return -1;
}
return 0;
}
static int
set_current(struct emu *emu)
{
emu->ev = player_ev(&emu->player);
emu->stream = player_stream(&emu->player);
struct lpt *lpt = system_get_lpt(emu->stream);
if (lpt == NULL) {
/* For now die if we have a unknown stream */
err("event from unknown stream: %s",
emu->stream->path);
return -1;
}
emu->loom = lpt->loom;
emu->proc = lpt->proc;
emu->thread = lpt->thread;
return 0;
}
static void
panic(struct emu *emu)
{
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
err("@@@@@@@@@@@@@@ EMULATOR PANIC @@@@@@@@@@@@@");
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
if (emu->ev != NULL) {
err("event: ");
err(" mcv=%s", emu->ev->mcv);
err(" rclock=%"PRIi64, emu->ev->rclock);
err(" sclock=%"PRIi64, emu->ev->sclock);
err(" dclock=%"PRIi64, emu->ev->dclock);
err(" payload_size=%zd", emu->ev->payload_size);
err(" is_jumbo=%d", emu->ev->is_jumbo);
}
if (emu->stream != NULL) {
err("stream: ");
err(" relpath=%s", emu->stream->relpath);
err(" offset=%"PRIi64, emu->stream->offset);
err(" clock_offset=%"PRIi64, emu->stream->clock_offset);
}
err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
}
int
emu_step(struct emu *emu)
{
int ret = player_step(&emu->player);
/* No more events */
if (ret > 0) {
emu->finished = 1;
return +1;
}
/* Error happened */
if (ret < 0) {
err("player_step failed");
return -1;
}
if (set_current(emu) != 0) {
err("cannot set current event information");
return -1;
}
dbg("----- mcv=%s dclock=%"PRIi64" -----", emu->ev->mcv, emu->ev->dclock);
emu_stat_update(&emu->stat, &emu->player);
/* Advance recorder clock */
if (recorder_advance(&emu->recorder, emu->ev->dclock) != 0) {
err("recorder_advance failed");
return -1;
}
/* Otherwise progress */
if (model_event(&emu->model, emu, emu->ev->m) != 0) {
err("model_event failed");
panic(emu);
return -1;
}
if (bay_propagate(&emu->bay) != 0) {
err("bay_propagate failed");
panic(emu);
return -1;
}
return 0;
}
int
emu_finish(struct emu *emu)
{
emu_stat_report(&emu->stat, &emu->player, 1);
int ret = 0;
if (model_finish(&emu->model, emu) != 0) {
err("model_finish failed");
ret = -1;
}
/* Finish the traces event if the model_finish failed */
if (recorder_finish(&emu->recorder) != 0) {
err("recorder_finish failed");
ret = -1;
}
return ret;
}