From c5332de86d02917b5a447ecef1328de6a07c7904 Mon Sep 17 00:00:00 2001 From: Stefan Wallentowitz Date: Tue, 1 Mar 2016 18:57:15 -0500 Subject: [PATCH] Support SV strings to readmemh, bug1040. Signed-off-by: Wilson Snyder --- Changes | 2 + include/verilated.cpp | 152 +++++++++++++++++---------------- include/verilated_heavy.h | 2 + test_regress/t/t_sys_readmem.v | 10 +++ 4 files changed, 93 insertions(+), 73 deletions(-) diff --git a/Changes b/Changes index 67802221a..9e61d1c23 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ indicates the contributor was also the author of the fix; Thanks! **** Support inlining interfaces, bug1018. [Johan Bjork] +**** Support SV strings to readmemh, bug1040. [Stefan Wallentowitz] + **** Fix unrolling complicated for-loop bounds, bug677. [Johan Bjork] **** Fix stats file containing multiple unroll entries, bug1020. [Johan Bjork] diff --git a/include/verilated.cpp b/include/verilated.cpp index b44df52f0..e5f98c564 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -956,11 +956,17 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, WDataInP ofilenamep, void* memp, IData start, IData end) { char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1]; _VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep); - FILE* fp = fopen(ofilenamez, "r"); + string ofilenames(ofilenamez); + return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end); +} + +void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords, + const string& ofilenamep, void* memp, IData start, IData end) { + FILE* fp = fopen(ofilenamep.c_str(), "r"); if (VL_UNLIKELY(!fp)) { - // We don't report the Verilog source filename as it slow to have to pass it down - vl_fatal (ofilenamez, 0, "", "$readmem file not found"); - return; + // We don't report the Verilog source filename as it slow to have to pass it down + vl_fatal (ofilenamep.c_str(), 0, "", "$readmem file not found"); + return; } // Prep for reading IData addr = start; @@ -975,81 +981,81 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords, // We process a character at a time, as then we don't need to deal // with changing buffer sizes dynamically, etc. while (1) { - int c = fgetc(fp); - if (VL_UNLIKELY(c==EOF)) break; - //printf("%d: Got '%c' Addr%x IN%d IgE%d IgC%d ninc%d\n", linenum, c, addr, innum, ignore_to_eol, ignore_to_cmt, needinc); - if (c=='\n') { linenum++; ignore_to_eol=false; if (innum) reading_addr=false; innum=false; } - else if (c=='\t' || c==' ' || c=='\r' || c=='\f') { if (innum) reading_addr=false; innum=false; } - // Skip // comments and detect /* comments - else if (ignore_to_cmt && lastc=='*' && c=='/') { - ignore_to_cmt = false; if (innum) reading_addr=false; innum=false; - } else if (!ignore_to_eol && !ignore_to_cmt) { - if (lastc=='/' && c=='*') { ignore_to_cmt = true; } - else if (lastc=='/' && c=='/') { ignore_to_eol = true; } - else if (c=='/') {} // Part of /* or // - else if (c=='_') {} - else if (c=='@') { reading_addr = true; innum=false; needinc=false; } - // Check for hex or binary digits as file format requests - else if (isxdigit(c)) { - c = tolower(c); - int value = (c >= 'a' ? (c-'a'+10) : (c-'0')); - if (!innum) { // Prep for next number - if (needinc) { addr++; needinc=false; } - } - if (reading_addr) { - // Decode @ addresses - if (!innum) addr=0; - addr = (addr<<4) + value; - } else { - needinc = true; - //printf(" Value width=%d @%x = %c\n", width, addr, c); - if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) { - vl_fatal (ofilenamez, linenum, "", "$readmem file address beyond bounds of array"); - } else { - int entry = addr - array_lsb; - QData shift = hex ? VL_ULL(4) : VL_ULL(1); - // Shift value in - if (width<=8) { - CData* datap = &((CData*)(memp))[entry]; - if (!innum) { *datap = 0; } - *datap = ((*datap << shift) + value) & VL_MASK_I(width); - } else if (width<=16) { - SData* datap = &((SData*)(memp))[entry]; - if (!innum) { *datap = 0; } - *datap = ((*datap << shift) + value) & VL_MASK_I(width); - } else if (width<=VL_WORDSIZE) { - IData* datap = &((IData*)(memp))[entry]; - if (!innum) { *datap = 0; } - *datap = ((*datap << shift) + value) & VL_MASK_I(width); - } else if (width<=VL_QUADSIZE) { - QData* datap = &((QData*)(memp))[entry]; - if (!innum) { *datap = 0; } - *datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width); - } else { - WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ]; - if (!innum) { VL_ZERO_RESET_W(width, datap); } - _VL_SHIFTL_INPLACE_W(width, datap, (IData)shift); - datap[0] |= value; - } - if (VL_UNLIKELY(value>=(1<= 'a' ? (c-'a'+10) : (c-'0')); + if (!innum) { // Prep for next number + if (needinc) { addr++; needinc=false; } + } + if (reading_addr) { + // Decode @ addresses + if (!innum) addr=0; + addr = (addr<<4) + value; + } else { + needinc = true; + //printf(" Value width=%d @%x = %c\n", width, addr, c); + if (VL_UNLIKELY(addr >= (IData)(depth+array_lsb) || addr < (IData)(array_lsb))) { + vl_fatal (ofilenamep.c_str(), linenum, "", "$readmem file address beyond bounds of array"); + } else { + int entry = addr - array_lsb; + QData shift = hex ? VL_ULL(4) : VL_ULL(1); + // Shift value in + if (width<=8) { + CData* datap = &((CData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=16) { + SData* datap = &((SData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=VL_WORDSIZE) { + IData* datap = &((IData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << shift) + value) & VL_MASK_I(width); + } else if (width<=VL_QUADSIZE) { + QData* datap = &((QData*)(memp))[entry]; + if (!innum) { *datap = 0; } + *datap = ((*datap << (QData)(shift)) + (QData)(value)) & VL_MASK_Q(width); + } else { + WDataOutP datap = &((WDataOutP)(memp))[ entry*VL_WORDS_I(width) ]; + if (!innum) { VL_ZERO_RESET_W(width, datap); } + _VL_SHIFTL_INPLACE_W(width, datap, (IData)shift); + datap[0] |= value; + } + if (VL_UNLIKELY(value>=(1<