/*
	sim_vcd_file.c

	Implements a Value Change Dump file outout to generate
	traces & curves and display them in gtkwave.

	Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>

 	This file is part of simavr.

	simavr is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	simavr is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with simavr.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef __SIM_VCD_FILE_H__
#define __SIM_VCD_FILE_H__

#include <stdio.h>
#include "sim_irq.h"
#include "fifo_declare.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Value Change dump module for simavr.
 *
 * This structure registers IRQ change hooks to various "source" IRQs
 * and dumps their values (if changed) at certain intervals into the VCD
 * file.
 *
 * It can also do the reverse, load a VCD file generated by for example
 * sigrock signal analyzer, and 'replay' digital input with the proper
 * timing.
 *
 * TODO: Add support for 'looping' a VCD input.
 */

#define AVR_VCD_MAX_SIGNALS 64

typedef struct avr_vcd_signal_t {
	/*
	 * For VCD output this is the IRQ we receive new values from.
	 * For VCD input, this is the IRQ we broadcast the values to
	 */
	avr_irq_t 		irq;
	char 			alias;			// vcd one character alias
	uint8_t			size;			// in bits
	char 			name[32];		// full human name
} avr_vcd_signal_t, *avr_vcd_signal_p;

typedef struct avr_vcd_log_t {
	uint64_t 		when;
	uint64_t			sigindex : 8,			// index in signal table
					floating : 1,
					value : 32;
} avr_vcd_log_t, *avr_vcd_log_p;

DECLARE_FIFO(avr_vcd_log_t, avr_vcd_fifo, 256);

struct argv_t;

typedef struct avr_vcd_t {
	struct avr_t *	avr;	// AVR we are attaching timers to..

	char *			filename;		// .vcd filename
	/* can be input OR output, not both */
	FILE * 			output;
	FILE * 			input;
	struct argv_t	* input_line;

	int 				signal_count;
	avr_vcd_signal_t	signal[AVR_VCD_MAX_SIGNALS];

	uint64_t 		start;
	uint64_t 		period;		// for output cycles
	uint64_t 		vcd_to_us;	// for input unit mapping

	avr_vcd_fifo_t	log;
} avr_vcd_t;

// initializes a new VCD trace file, and returns zero if all is well
int
avr_vcd_init(
		struct avr_t * avr,
		const char * filename, 	// filename to write
		avr_vcd_t * vcd,		// vcd struct to initialize
		uint32_t	period );	// file flushing period is in usec
int
avr_vcd_init_input(
		struct avr_t * avr,
		const char * filename, 	// filename to read
		avr_vcd_t * vcd );		// vcd struct to initialize
void
avr_vcd_close(
		avr_vcd_t * vcd );

// Add a trace signal to the vcd file. Must be called before avr_vcd_start()
int
avr_vcd_add_signal(
		avr_vcd_t * vcd,
		avr_irq_t * signal_irq,
		int signal_bit_size,
		const char * name );

// Starts recording the signal value into the file
int
avr_vcd_start(
		avr_vcd_t * vcd);
// stops recording signal values into the file
int
avr_vcd_stop(
		avr_vcd_t * vcd);

#ifdef __cplusplus
};
#endif

#endif /* __SIM_VCD_FILE_H__ */
