// Filename : simulation_serialization.cpp

#include "simulation_serialization.h"
#include "spacecomp_pre_cpp.h"

#include <cstdio>
#include <string>

// Do NOT move macros, functions and includes beginning with "spacecomp".

simulation_serialization::simulation_serialization(SPACECOMP_CTOR_PARAMS(simulation_serialization, INDEX))
	: sdevice(SPACECOMP_SDBASE_ARGS(simulation_serialization, INDEX))
	, SPACECOMP_START_ILIST(simulation_serialization, INDEX)
	, m_content(0), m_image_size(0)
{
	std::string path = spacelib_global::get_project_path() + "/imports/images/image_out.pgm";
	m_file = fopen(path.c_str(), "wb");
	if (m_file == 0) {
		printf("error while opening output image\n");
		exit(1);
	}
}

simulation_serialization::~simulation_serialization() {}

/**
 * Called on slave access.
 *
 * @param trans TLM 2.0 generic payload.
 * @param delay TLM 2.0 delay parameter.
 */
void simulation_serialization::access(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay) {
	uint32_t written_bytes = 0;
	// reached offset
	unsigned long offset = get_offset(trans);

	if (trans.is_read())
		SpacePrint("reading offset %#X @[%f s]\n", offset, sc_core::sc_time_stamp().to_seconds());
	else {
		switch(offset) {
	    case START_REG:
	    	m_image_size = *(uint32_t*)trans.get_data_ptr();
	    	m_content = new uint8_t[m_image_size];
	        break;
	    case DONE_REG:
			written_bytes = fwrite(m_content, 1, m_image_size, m_file);

			if (written_bytes != m_image_size) {
				printf("%s: error while writing\n", name());
				exit(1);
			}

			fclose(m_file);
			delete[] m_content;
			sc_stop();
	        break;
		default:
			std::memcpy(&m_content[offset - PIXEL_REG], trans.get_data_ptr(), trans.get_data_length());
	        break;
		}
	}

	trans.set_response_status(tlm::TLM_OK_RESPONSE);	// don't forget to set the TLM 2.0 response status
	delay += get_clock_period();	// simulate device access delay
}

#include "spacecomp_post_cpp.h"