/* ** 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. */ /* * verilog_vardecl.c 修改记录: 202106061102: rxh, initial version */ #include "stdio.h" #include "stdlib.h" #include "string.h" #include "object.h" #include "dlist.h" #include "bignumber.h" #include "conststring.h" #include "verilog_parsetree.h" #include "verilog_module.h" #include "verilog_expr.h" #include "verilog_varsel.h" #include "verilog_assignment.h" #define IMPLEMENT_GUID #include "verilog_vardecl.h" #undef IMPLEMENT_GUID typedef struct _sVarDecl { OBJECT_HEADER INTERFACE_DECLARE(IVerilogNode) VERILOGNODE_VARDECLARE DLIST_VARDECLARE verilogVarDecl data; }sVarDecl; OBJECT_FUNCDECLARE(vardecl, CLSID_VERILOG_VARDECL); VERILOGNODE_FUNCDECLARE(vardecl, CLSID_VERILOG_VARDECL, sVarDecl); DLIST_FUNCIMPL(vardecl, CLSID_VERILOG_VARDECL, sVarDecl); OBJECT_FUNCIMPL(vardecl, sVarDecl, CLSID_VERILOG_VARDECL); QUERYINTERFACE_BEGIN(vardecl, CLSID_VERILOG_VARDECL) QUERYINTERFACE_ITEM(IID_VERILOG_NODE, IVerilogNode, sVarDecl) QUERYINTERFACE_ITEM(IID_DLIST, IDList, sVarDecl) QUERYINTERFACE_END static const char *vardeclModuleInfo() { return "1.0.0-20210606.1108 Verilog Var Declaration "; } static int vardeclCreate(const PARAMITEM * pParams, int paramcount, HOBJECT * pObject) { sVarDecl * pobj; pobj = (sVarDecl *)malloc(sizeof(sVarDecl)); if (pobj == NULL) return -1; memset(pobj, 0, sizeof(sVarDecl)); *pObject = 0; DLIST_VARINIT(pobj, vardecl); VERILOGNODE_VARINIT(pobj, CLSID_VERILOG_VARDECL); INTERFACE_INIT(IVerilogNode, pobj, vardecl, verilognode); /*返回生成的对象*/ OBJECT_RETURN_GEN(vardecl, pobj, pObject, CLSID_VERILOG_VARDECL); return EIID_OK; } static void vardeclDestroy(HOBJECT object) { sVarDecl * pobj; pobj = (sVarDecl *)objectThis(object); objectRelease(pobj->data.name); objectRelease(pobj->data.assignexpr); objectRelease(pobj->data.range_msb); objectRelease(pobj->data.range_lsb); dlistRemoveAll(pobj->data.attributes); objectRelease(pobj->data.attributes); dlistRemoveAll(pobj->data.dimensions); objectRelease(pobj->data.dimensions); memset(pobj, 0, sizeof(sVarDecl)); free(pobj); } /* 功能:判断对象是否是一个有效对象 参数: object -- 对象数据指针 返回值: 0 -- 对象是无效的 1 -- 对象是有效的 */ static int vardeclValid(HOBJECT object) { return 1; } static int output_range(FILE* pFile, int opt, int type, IVerilogNode** msb, IVerilogNode** lsb) { if (type == RANGE_TYPE_NONE) return 0; if (type == RANGE_TYPE_BITSELECT) { fprintf(pFile, " ["); objectCall2(msb, dump, pFile, opt); fprintf(pFile, "] "); return 0; } fprintf(pFile, " ["); objectCall2(msb, dump, pFile, opt); if (type == RANGE_TYPE_PARTSELECT) fprintf(pFile, ":"); else if (type == RANGE_TYPE_STARTPLUSWIDTH) fprintf(pFile, "+:"); else if (type == RANGE_TYPE_STARTMINUSWIDTH) fprintf(pFile, "-:"); objectCall2(lsb, dump, pFile, opt); fprintf(pFile, "] "); return 0; } static const char* var_type_name[] = { "", "supply0", "supply1", "tri", "triand", "trior", "tri0", "tri1", "uwire", "wire", "wand", "wor", "integer", "time", "reg", }; static int vardecl_verilognode_dump(HOBJECT object, FILE * pFile, int opt) { sVarDecl * pobj; pobj = (sVarDecl *)objectThis(object); /* attribute_instance_list net_type drive_strength_option vectored_or_scalared_option signed_option range_option delay3_option list_of_net */ fprintf(pFile, " "); if (dlistItemCount(pobj->data.attributes) > 0) { fprintf(pFile, "(* "); verilog_dump_node_list(pobj->data.attributes, pFile, opt, ", ", 5); fprintf(pFile, " *) "); } fprintf(pFile, var_type_name[pobj->data.type]); output_range(pFile, opt, pobj->data.range_type, pobj->data.range_msb, pobj->data.range_lsb); fprintf(pFile, " %s", conststringFromVar(pobj->data.name)); if (pobj->data.assignexpr != NULL) { fprintf(pFile, " = "); objectCall2(pobj->data.assignexpr, dump, pFile, opt); } fprintf(pFile, ";\n"); return 0; } static int vardecl_verilognode_procheck(HOBJECT object, HOBJECT module, void * param) { sVarDecl* pobj; verilogModule* pmodule = verilogModuleGetData(module); pobj = (sVarDecl*)objectThis(object); objectCall2(pobj->data.assignexpr, procheck, module, param); objectCall2(pobj->data.range_msb, procheck, module, param); objectCall2(pobj->data.range_lsb, procheck, module, param); {/*如果声明中带赋值,则将赋值加入到持续性赋值中去*/ if (pobj->data.assignexpr != NULL) { IDListVarPtr lvalue, itemlist; HOBJECT continuous_assign; lvalue = dlistCreate(); dlistAppendItem(lvalue, verilogparseCreateVarSel( pobj->data.name, //const char * name, RANGE_TYPE_NONE, //int range_type, NULL, //HOBJECT range_msb, NULL //HOBJECT range_lsb )); continuous_assign = verilogparseCreateAssignment( 0, lvalue, NULL, RANGE_TYPE_NONE, 0, pobj->data.assignexpr, pobj->data.attributes ); itemlist = dlistCreate(); dlistAppendItem(itemlist, continuous_assign); verilogparseAddModuleItems(module, itemlist, MODULE_ITEM_TYPE_CONTINUOUS_ASSIGNMENT); //objectRelease(pobj->data.assignexpr); pobj->data.assignexpr = NULL; } } pobj->data.index = pmodule->paramindex++; return 0; } static int vardecl_verilognode_gencode(HOBJECT object, FILE * pFile, HOBJECT module, void * param) { sVarDecl* pobj; int paramcount; verilogModule* moduleinfo; moduleinfo = verilogModuleGetData(module); paramcount = dlistItemCount(moduleinfo->module_parameters); pobj = (sVarDecl*)objectThis(object); if (pobj->data.range_type == RANGE_TYPE_NONE) { fprintf(pFile, "\tnets[%3d] = hdl4seCreateUnit(module, CLSID_HDL4SE_WIRE, \" 1\", \"%s\");\n", pobj->data.index, pobj->data.name->string); fprintf(pFile, "\t__netswidth[%d] = 1;\n", pobj->data.index); } else if (pobj->data.range_type == RANGE_TYPE_PARTSELECT) { verilogExpr* lsb; verilogExpr* msb; lsb = verilogExprGetData(pobj->data.range_lsb); msb = verilogExprGetData(pobj->data.range_msb); if (lsb != NULL && lsb->exprtype == EXPRTYPE_BIGNUMBER && msb != NULL && msb->exprtype == EXPRTYPE_BIGNUMBER) { int width; IBigNumber** temp = bigintegerCreate(32); objectCall2(temp, Sub, msb->bignumber, lsb->bignumber); objectCall2(temp, AddInt32, temp, 1); objectCall1(temp, GetInt32, &width); objectRelease(temp); fprintf(pFile, "\tnets[%3d] = hdl4seCreateUnit(module, CLSID_HDL4SE_WIRE, \"%3d\", \"%s\");\n", pobj->data.index, width, pobj->data.name->string); fprintf(pFile, "\t__netswidth[%d] = %d;\n", pobj->data.index, width); } else { int exprcount; fprintf(pFile, "\t\t{/*%3d %s */\n", pobj->data.index, pobj->data.name->string); fprintf(pFile, "\t\t\tint wirewidth;\n"); fprintf(pFile, "\t\t\tchar instanceparam[256];\n"); fprintf(pFile, "\t\t\tconst expr_code expr_info[] = {\n"); exprcount = verilogparseGenConstExpr(pFile, "\t\t\t\t", pobj->data.range_msb, module); exprcount += verilogparseGenConstExpr(pFile, "\t\t\t\t", pobj->data.range_lsb, module); fprintf(pFile, "\t\t\t\t{.exprtype=EXPRTYPE_BINOP, .op=OP_MINUS},\n"); fprintf(pFile, "\t\t\t\t{.exprtype=EXPRTYPE_NUMBER, .value=\"1\"},\n"); fprintf(pFile, "\t\t\t\t{.exprtype=EXPRTYPE_BINOP, .op=OP_PLUS},\n"); exprcount += 3; fprintf(pFile, "\t\t\t};\n"); fprintf(pFile, "\t\t\twirewidth = const_expr_eval(%d, expr_info, %d, %s);\n", exprcount, paramcount, paramcount > 0 ? "parameters" : "NULL"); fprintf(pFile, "\t\t\tsprintf(instanceparam, \"%%d\", wirewidth);\n"); fprintf(pFile, "\t\t\tnets[%3d] = hdl4seCreateUnit(module, CLSID_HDL4SE_WIRE, instanceparam, \"%s\");\n", pobj->data.index, pobj->data.name->string); fprintf(pFile, "\t__netswidth[%d] = wirewidth;\n", pobj->data.index); fprintf(pFile, "\t\t};\n"); } } return 0; } HOBJECT verilogparseCreateVarDecl(IConstStringVar* name) { HOBJECT vardecl = NULL; sVarDecl * pobj; A_u_t_o_registor_vardecl(); objectCreate(CLSID_VERILOG_VARDECL, NULL, 0, &vardecl); if (vardecl == NULL) return NULL; pobj = (sVarDecl *)objectThis(vardecl); objectQueryInterface(name, IID_CONSTSTRING, (void**)&pobj->data.name); return vardecl; } int verilogparseVarDeclSetAssignExpr(HOBJECT object, HOBJECT expr) { sVarDecl* pobj; if (!objectIsClass(object, CLSID_VERILOG_VARDECL)) return -1; pobj = (sVarDecl*)objectThis(object); objectRelease(pobj->data.assignexpr); objectQueryInterface(expr, IID_VERILOG_NODE, (void**)&pobj->data.assignexpr); return 0; } int verilogparseVarDeclSetDimensions(HOBJECT object, IDListVar* dimensions) { sVarDecl* pobj; if (!objectIsClass(object, CLSID_VERILOG_VARDECL)) return -1; pobj = (sVarDecl*)objectThis(object); pobj->data.dimensions = dimensions; objectAddRef(pobj->data.dimensions); return 0; } int verilogparseVarDeclSetOptions(HOBJECT object, int type, IDListVar* attributes, int vectored_or_scalared, int issigned, int range_type, HOBJECT range_msb, HOBJECT range_lsb ) { #define ASSIGN_MEMBER(m) \ objectRelease(pobj->data.m); \ pobj->data.m = NULL; \ objectQueryInterface(m, IID_VERILOG_NODE, (void**)&pobj->data.m); sVarDecl* pobj; if (!objectIsClass(object, CLSID_VERILOG_VARDECL)) return -1; pobj = (sVarDecl*)objectThis(object); pobj->data.attributes = attributes; objectAddRef(pobj->data.attributes); pobj->data.type = type; pobj->data.vectored_or_scalared = vectored_or_scalared; pobj->data.issigned = issigned; pobj->data.range_type = range_type; ASSIGN_MEMBER(range_msb); ASSIGN_MEMBER(range_lsb); return 0; } verilogVarDecl* verilogVarDeclGetData(HOBJECT object) { sVarDecl* pobj; if (!objectIsClass(object, CLSID_VERILOG_VARDECL)) return NULL; pobj = (sVarDecl*)objectThis(object); return &pobj->data; }