184 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
 | 
						|
 * SPDX-License-Identifier: GPL-3.0-or-later */
 | 
						|
 | 
						|
#define _POSIX_C_SOURCE 2
 | 
						|
 | 
						|
//#define ENABLE_DEBUG
 | 
						|
 | 
						|
#include "emu.h"
 | 
						|
 | 
						|
#include <unistd.h>
 | 
						|
#include "models.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'\n", 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'\n",
 | 
						|
				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'\n",
 | 
						|
				emu->args.tracedir);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	emu_stat_init(&emu->stat);
 | 
						|
 | 
						|
	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;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
emu_connect(struct emu *emu)
 | 
						|
{
 | 
						|
	if (model_connect(&emu->model, emu) != 0) {
 | 
						|
		err("model_connect failed");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
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);
 | 
						|
	emu->loom = lpt->loom;
 | 
						|
	emu->proc = lpt->proc;
 | 
						|
	emu->thread = lpt->thread;
 | 
						|
}
 | 
						|
 | 
						|
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=%ld", emu->ev->rclock);
 | 
						|
		err("  sclock=%ld", emu->ev->sclock);
 | 
						|
		err("  dclock=%ld", emu->ev->dclock);
 | 
						|
		err("  payload_size=%ld", 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=%ld", emu->stream->offset);
 | 
						|
		err("  clock_offset=%ld", emu->stream->clock_offset);
 | 
						|
	}
 | 
						|
	err("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
emu_step(struct emu *emu)
 | 
						|
{
 | 
						|
	int ret = player_step(&emu->player);
 | 
						|
 | 
						|
	/* No more events */
 | 
						|
	if (ret > 0)
 | 
						|
		return +1;
 | 
						|
 | 
						|
	/* Error happened */
 | 
						|
	if (ret < 0) {
 | 
						|
		err("player_step failed");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	set_current(emu);
 | 
						|
 | 
						|
	dbg("----- mvc=%s dclock=%ld -----", 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);
 | 
						|
 | 
						|
	if (model_finish(&emu->model, emu) != 0) {
 | 
						|
		err("model_finish failed");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	if (recorder_finish(&emu->recorder) != 0) {
 | 
						|
		err("recorder_finish failed");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 |