/*
** 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.
*/

/*
* hdl4secell.c
  修改记录：
	202105180851: rxh, initial version
*/
#include "stdlib.h" 
#include "stdio.h"
#include "object.h"
#include "bignumber.h"

#define IMPLEMENT_GUID
#include "hdl4secell.h"
#undef IMPLEMENT_GUID

/*
  用CLSID和实例化参数生成一个电路单元，如果生成成功，电路单元而且parent是一个合法的Module，
  则单元以name命名加入到parent中
*/

static int hdl4secell_registed = 0;

extern OFUNCPTR A_u_t_o_registor_hdl4se_reg;
extern OFUNCPTR A_u_t_o_registor_hdl4se_unop;
extern OFUNCPTR A_u_t_o_registor_hdl4se_binop;
extern OFUNCPTR A_u_t_o_registor_hdl4se_wire;
extern OFUNCPTR A_u_t_o_registor_hdl4se_const;
extern OFUNCPTR A_u_t_o_registor_hdl4se_module;
extern OFUNCPTR A_u_t_o_registor_hdl4se_bind2;
extern OFUNCPTR A_u_t_o_registor_hdl4se_bind3;
extern OFUNCPTR A_u_t_o_registor_hdl4se_bind4;
extern OFUNCPTR A_u_t_o_registor_hdl4se_split2;
extern OFUNCPTR A_u_t_o_registor_hdl4se_split4;
extern OFUNCPTR A_u_t_o_registor_hdl4se_mux2;
extern OFUNCPTR A_u_t_o_registor_hdl4se_mux4;
extern OFUNCPTR A_u_t_o_registor_hdl4se_mux8;
extern OFUNCPTR A_u_t_o_registor_hdl4se_mux16;

IHDL4SEUnit** hdl4seCreateUnit(IHDL4SEModule** parent, IIDTYPE clsid, char* instanceparam, char* name)
{
	PARAMITEM param[3];
	IHDL4SEUnit** result = NULL;
	param[0].name = PARAMID_HDL4SE_UNIT_INSTANCE_PARAMETERS;
	param[0].pvalue = instanceparam;
	param[1].name = PARAMID_HDL4SE_UNIT_NAME;
	param[1].pvalue = name;
	param[2].name = PARAMID_HDL4SE_UNIT_PARENT;
	param[2].pvalue = parent;
	if (hdl4secell_registed == 0) {
		A_u_t_o_registor_hdl4se_reg();
		A_u_t_o_registor_hdl4se_unop();
		A_u_t_o_registor_hdl4se_binop();
		A_u_t_o_registor_hdl4se_wire();
		A_u_t_o_registor_hdl4se_const();
		A_u_t_o_registor_hdl4se_module();
		A_u_t_o_registor_hdl4se_bind2();
		A_u_t_o_registor_hdl4se_bind3();
		A_u_t_o_registor_hdl4se_bind4();
		A_u_t_o_registor_hdl4se_split2();
		A_u_t_o_registor_hdl4se_split4();
		A_u_t_o_registor_hdl4se_mux2();
		A_u_t_o_registor_hdl4se_mux4();
		A_u_t_o_registor_hdl4se_mux8();
		A_u_t_o_registor_hdl4se_mux16();
		hdl4secell_registed = 1;
	}
	if (EIID_OK != objectCreateEx(clsid, param, 3, IID_HDL4SEUNIT, (const void**)&result)) {
		printf("%s[%s] create failed\n", name, instanceparam);
		return NULL;
	}
	objectCall1(parent, AddUnit, result);
	return result;
}

int hdl4sedetectorTraversal(HOBJECT object, hdl4se_detector_TraversalFunc func, const char* pathname, void* param)
{
	IHDL4SEDetector** detector;
	if (0 == objectQueryInterface(object, IID_HDL4SEDETECTOR, (void**)&detector)) {
		int count, i, pathlen;
		char* pname;
		const char* unitname = NULL;
		pathlen = strlen(pathname) + 256;
		pname = (char*)malloc(pathlen);
		if (pname == NULL)
			return -2;
		strcpy(pname, pathname);
		strcat(pname, "/");
		objectCall1(detector, GetName, &unitname);
		if (unitname == NULL) {
			free(pname);
			return -3;
		}
		strcat(pname, unitname);
		if (func(detector, pname, param) != 0)
			return -1;
		count = objectCall0(detector, GetUnitCount);
		for (i = 0; i < count; i++) {
			HOBJECT unit;
			objectCall2(detector, GetUnit, i, &unit);
			if (hdl4sedetectorTraversal(unit, func, pname, param) != 0)
				return -1;
		}
		free(pname);
		objectRelease(detector);
	}
	return 0;
}