

/*
** HDL4SE: 软件Verilog综合仿真平台
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** LCOM: 轻量级组件对象模型
** Copyright (C) 2021-2021, raoxianhong<raoxianhong@163.net>
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
**   this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
**   this list of conditions and the following disclaimer in the documentation
**   and/or other materials provided with the distribution.
** * The name of the author may be used to endorse or promote products
**   derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
** THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "object.h"
#include "bignumber.h"
#include "hdl4secell.h"
#include "hdl4sesim.h"
#include "counter.h"
#include "digitled.h"

IHDL4SESimulator** sim;
IHDL4SEUnit** topmodule; 
IHDL4SEUnit** gui;
unsigned long long clocks = 0;

IHDL4SEUnit** hdl4seCreateMain2(IHDL4SEModule** parent, char* instanceparam, char* name);

static int running = 1;



int StopRunning()
{
	running = 0;
	return 0;
}

static int hdl4se_print_all_signal(IHDL4SEDetector** detector, const char * pathname, int *pwidth)
{
	int i;
	int count;
	int width;
	const char* name;
	count = objectCall0(detector, GetSignalCount);
	(*pwidth)++;
	for (i = 0; i < count; i++) {
		objectCall3(detector, GetSignalInfo, i, &name, &width);
		printf("%s/%s, %d\n", pathname, name, width);
	}
	return 0;
}

typedef struct s_signal_item {
	const char* unitname;
	const char* signalname;
	IHDL4SEDetector** detector;
	int index;
	int width;
} signal_item;

signal_item signal_list[] = {
	{"/simulator/digitled", "nwReset", NULL, 0, 0},
	{"/simulator/digitled", "wWrite", NULL, 0, 0},
	{"/simulator/digitled", "bWriteAddr", NULL, 0, 0},
	{"/simulator/digitled", "bWriteData", NULL, 0, 0},
	{"/simulator/digitled", "wRead", NULL, 0, 0},
	{"/simulator/digitled", "bReadAddr", NULL, 0, 0},
	{"/simulator/digitled", "bReadData", NULL, 0, 0},
	{"/simulator/main",		"2.bWriteAddr", NULL, 0, 0},
	{"/simulator/main",		"3.bWriteData", NULL, 0, 0},
	{"/simulator/main/bind4_3210", "out", NULL, 0, 0},
	{"/simulator/main/bind4_7654", "out", NULL, 0, 0},
	{"/simulator/main/counter0", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter1", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter2", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter3", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter4", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter5", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter6", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/counter7", "2.bCounter", NULL, 0, 0},
	{"/simulator/main/dec2seg0", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg1", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg2", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg3", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg4", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg5", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg6", "1.seg", NULL, 0, 0},
	{"/simulator/main/dec2seg7", "1.seg", NULL, 0, 0},
};

#define signal_list_count (sizeof(signal_list) / sizeof(signal_list[0]))

static int hdl4se_init_signal_list(IHDL4SEDetector** detector, const char* pathname, int *pcount)
{
	int i, j;
	int count;
	int width;
	const char* name;
	for (j = 0; j < signal_list_count; j++) {
		if (strcmp(pathname, signal_list[j].unitname) == 0) {
			count = objectCall0(detector, GetSignalCount);
			for (i = 0; i < count; i++) {
				objectCall3(detector, GetSignalInfo, i, &name, &width);
				if (strcmp(name, signal_list[j].signalname) == 0) {
					signal_list[j].detector = detector;
					signal_list[j].index = i;
					signal_list[j].width = width;
					printf("sig: %s, unit=%s, index=%d, width=%d\n", name, pathname, i, width);
					(*pcount)++;
				}
			}
		}
	}
	return 0;
}

FILE* pSignalFile = NULL;
IBigNumber** signal_value = NULL;

static int hdl4se_print_signal_list_header()
{
	int i;
	fprintf(pSignalFile, "clocks");
	for (i = 0; i < signal_list_count; i++) {
		fprintf(pSignalFile, ",%s/%s", signal_list[i].unitname, signal_list[i].signalname);
	}
	fprintf(pSignalFile, "\n");
	return 0;
}

static int hdl4se_print_signal_list_detector()
{
	int i;
	/* 
	   我们可以设置记录条件，比如，看到bDataRead数据不为零才记录，
	   此时必然是由按键消息了 
	*/
	{
		unsigned int v;
		objectCall2(signal_value, SetWidth, 32, 0);
		objectCall2(signal_list[6].detector, GetSignalValue, signal_list[6].index, signal_value);
		objectCall1(signal_value, GetInt32, &v);
		if (v != 4) /* 只有F3按下的时候才记录 */
			return 0;
	}
	fprintf(pSignalFile, "%lld", clocks);
	for (i = 0; i < signal_list_count; i++) {
		unsigned int v;
		objectCall2(signal_value, SetWidth, 32, 0);
		objectCall2(signal_list[i].detector, GetSignalValue, signal_list[i].index, signal_value);
		objectCall2(signal_value, SetWidth, signal_list[i].width, 1);
		objectCall1(signal_value, GetInt32, &v);
		if (signal_list[i].width < 9) {
			fprintf(pSignalFile, ",%d", v & ( (1 << signal_list[i].width) - 1));
		}
		else {
			fprintf(pSignalFile, ",%08x", v);
		}
	}
	fprintf(pSignalFile, "\n");
	return 0;
}


int main(int argc, char* argv[])
{
	int width;
	int count, unitcount;
	IHDL4SEUnit** sim_unit;
	sim = hdl4sesimCreateSimulator();
	topmodule = hdl4seCreateMain(NULL, "", "main");
	gui = guiCreate(0xf0000000, "digitled");
	objectCall1(sim, SetTopModule, topmodule);
	objectCall1(sim, AddDevice, gui);
	objectCall1(sim, SetReset, 0);
	unitcount = 0;
	hdl4sedetectorTraversal(sim, hdl4se_print_all_signal, "", &unitcount);
	count = 0;
	pSignalFile = fopen("digitled.csv", "w");
	signal_value = bigintegerCreate(32);
	hdl4se_print_signal_list_header();
	hdl4sedetectorTraversal(sim, hdl4se_init_signal_list, "", &count);
	printf("want %d, inited %d, total %d units\n", signal_list_count, count, unitcount);
	objectQueryInterface(sim, IID_HDL4SEUNIT, (void**) &sim_unit);
	do {
		//objectCall0(sim, RunClockTick);
		objectCall0(sim_unit, ClkTick);
		hdl4se_print_signal_list_detector();
		objectCall0(sim_unit, Setup);
		clocks++;
		if (clocks == 4)
			objectCall1(sim, SetReset, 1);
	} while (running);
	objectRelease(signal_value);
	fclose(pSignalFile);
	return 0;
}
