/* ** HDL4SE: 软件Verilog综合仿真平台 ** Copyright (C) 2021-2021, raoxianhong ** LCOM: 轻量级组件对象模型 ** Copyright (C) 2021-2021, raoxianhong ** 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. */ /* * hdl4sesim.c 修改记录: 202105180851: rxh, initial version 202105241905:rxh, 增加Detector接口 202106270618: rxh, 取消device的概念,仿真器只提供提供wClk信号和nwReset信号 202107181746: rxh, 取消Unit,Detector接口 202107230621: rxh, 支持多线程的版本 */ #include "omp.h" #include "stdlib.h" #include "stdio.h" #include "string.h" #include "object.h" #include "bignumber.h" #include "hdl4secell.h" #include "threadlock.h" #include "windows.h" #define IMPLEMENT_GUID #include "hdl4sesim.h" #undef IMPLEMENT_GUID typedef struct _sHDL4SESim { OBJECT_HEADER INTERFACE_DECLARE(IHDL4SESimulator) HDL4SESIMULATOR_VARDECLARE HDL4SEMODULE_VARDECLARE IHDL4SEModuleVar* topmodule; PointerArray multithreadmodules; PointerArray singlethreadmodules; unsigned long long clocks; int reset; int clk; }sHDL4SESim; OBJECT_FUNCDECLARE(hdl4sesim, CLSID_HDL4SESIMULATOR); HDL4SESIMULATOR_FUNCDECLARE(hdl4sesim, CLSID_HDL4SESIMULATOR, sHDL4SESim); HDL4SEMODULE_FUNCIMPL(hdl4sesim, CLSID_HDL4SESIMULATOR, sHDL4SESim); OBJECT_FUNCIMPL(hdl4sesim, sHDL4SESim, CLSID_HDL4SESIMULATOR); QUERYINTERFACE_BEGIN(hdl4sesim, CLSID_HDL4SESIMULATOR) QUERYINTERFACE_ITEM(IID_HDL4SEMODULE, IHDL4SEModule, sHDL4SESim) QUERYINTERFACE_ITEM(IID_HDL4SESIMULATOR, IHDL4SESimulator, sHDL4SESim) QUERYINTERFACE_END static const char* hdl4sesimModuleInfo() { return "0.4.0-20210718.1746 HDL4SE simulator"; } static int hdl4sesim_gen_nwReset(sHDL4SESim* pobj) { hdl4se_module_SetVarUint32(&pobj->data, 1, pobj->reset); return 0; } static int hdl4sesim_gen_wClk(sHDL4SESim* pobj) { hdl4se_module_SetVarUint32(&pobj->data, 0, pobj->clk); return 0; } #define M_ID(id) hdl4sesim##id IDLIST VID(wClk), VID(nwReset), END_IDLIST static int hdl4sesimCreate(const PARAMITEM* pParams, int paramcount, HOBJECT* pObject) { sHDL4SESim* pobj; pobj = (sHDL4SESim*)mt_malloc(sizeof(sHDL4SESim)); if (pobj == NULL) return -1; *pObject = 0; INTERFACE_INIT(IHDL4SESimulator, pobj, hdl4sesim, hdl4se_simulator); HDL4SEMODULE_VARINIT(pobj, hdl4sesim); pobj->topmodule = NULL; pointerarrayInit(&pobj->multithreadmodules); pointerarrayInit(&pobj->singlethreadmodules); pobj->reset = 0; pobj->clk = 0; pobj->clocks = 0; PORT_OUT(wClk, 1); PORT_OUT(nwReset, 1); GEN_FUNC("wClk", hdl4sesim_gen_wClk); GEN_FUNC("nwReset", hdl4sesim_gen_nwReset); vartempInit(); crtinit(); /* 返回生成的对象 */ OBJECT_RETURN_GEN(hdl4sesim, pobj, pObject, CLSID_HDL4SESIMULATOR); return EIID_OK; } static int objRelease(HOBJECT obj) { return objectRelease(obj); } static void hdl4sesimDestroy(HOBJECT object) { sHDL4SESim* pobj; int i; pobj = (sHDL4SESim*)objectThis(object); hdl4se_module_DeInit(&pobj->data); objectRelease(pobj->topmodule); pointerarrayDestroy(&pobj->multithreadmodules, objRelease); pointerarrayDestroy(&pobj->singlethreadmodules, objRelease); memset(pobj, 0, sizeof(sHDL4SESim)); mt_free(pobj); } static int hdl4sesimValid(HOBJECT object) { sHDL4SESim* pobj; pobj = (sHDL4SESim*)objectThis(object); return 1; } typedef int (*hdl4se_module_TraversalFunc)(HOBJECT module, sHDL4SESim* param); static int hdl4semoduleTraversal(HOBJECT object, hdl4se_module_TraversalFunc func, sHDL4SESim* param) { IHDL4SEModuleVar* module; func(object, param); if (0 == objectQueryInterface(object, IID_HDL4SEMODULE, (void**)&module)) { int count, i; count = hdl4se_module_GetModuleCount(&module->data); for (i = 0; i < count; i++) { IHDL4SEModuleVar* unit; hdl4se_module_GetModule(&module->data, i, &unit); if (hdl4semoduleTraversal(unit, func, param) != 0) return -1; } objectRelease(module); } return 0; } static int hdl4sesim_collect_module(HOBJECT module, sHDL4SESim* pobj) { IHDL4SEModuleVar* m; int canruninthread = 0; if (EIID_OK == objectQueryInterface(module, IID_HDL4SEMODULE, (const void**)&m)) { canruninthread = m->data.canruninthread; if (canruninthread) { pointerarrayAddItem(&pobj->multithreadmodules, m); } else { pointerarrayAddItem(&pobj->singlethreadmodules, m); } } return 0; } static int hdl4sesim_hdl4se_simulator_SetTopModule(HOBJECT object, HOBJECT topmodule) { sHDL4SESim* pobj; void* a[1024]; pobj = (sHDL4SESim*)objectThis(object); objectQueryInterface(topmodule, IID_HDL4SEMODULE, (const void**)&pobj->topmodule); hdl4semoduleTraversal(pobj->topmodule, hdl4sesim_collect_module, pobj); /*连接topmodule到sim模块,0.wClk, 1.nwReset*/ hdl4se_module_ConnectInput(&pobj->topmodule->data, 0, object, 0); hdl4se_module_ConnectInput(&pobj->topmodule->data, 1, object, 1); return 0; } static int hdl4sesim_hdl4se_simulator_SetReset(HOBJECT object, int reset) { sHDL4SESim* pobj; pobj = (sHDL4SESim*)objectThis(object); pobj->reset = reset; return 0; } #define THREADCOUNT 4 static int hdl4sesim_hdl4se_simulator_ClkTick(HOBJECT object) { sHDL4SESim* pobj; int i; pobj = (sHDL4SESim*)objectThis(object); pobj->clk = 0; hdl4se_module_ClkTick(&pobj->data); for (i = 0; i < pobj->singlethreadmodules.itemcount; i++) { hdl4se_module_ClkTick(&((IHDL4SEModuleVar*)(pobj->singlethreadmodules.array[i]))->data); } #pragma omp parallel for num_threads(THREADCOUNT) for (i = 0; i < pobj->multithreadmodules.itemcount; i++) { hdl4se_module_ClkTick(&((IHDL4SEModuleVar*)(pobj->multithreadmodules.array[i]))->data); } return 0; } static int hdl4sesim_hdl4se_simulator_Setup(HOBJECT object) { sHDL4SESim* pobj; int i; pobj = (sHDL4SESim*)objectThis(object); pobj->clk = 1; pobj->clocks++; vartempClean(); hdl4se_module_Setup(&pobj->data); for (i = 0; i < pobj->singlethreadmodules.itemcount; i++) { hdl4se_module_Setup(&((IHDL4SEModuleVar*)(pobj->singlethreadmodules.array[i]))->data); } #pragma omp parallel for num_threads(THREADCOUNT) for (i = 0; i < pobj->multithreadmodules.itemcount; i++) { hdl4se_module_Setup(&((IHDL4SEModuleVar*)(pobj->multithreadmodules.array[i]))->data); } return 0; } static long long hdl4sesim_hdl4se_simulator_GetClock(HOBJECT object) { sHDL4SESim* pobj; pobj = (sHDL4SESim*)objectThis(object); return pobj->clocks; } IHDL4SESimulator** hdl4sesimCreateSimulator() { int ret; IHDL4SESimulator** sim; A_u_t_o_registor_hdl4sesim(); ret = objectCreateEx(CLSID_HDL4SESIMULATOR, NULL, 0, IID_HDL4SESIMULATOR, (const void**)&sim); return sim; }