Merge from master
This commit is contained in:
commit
02f18fc21b
6
Changes
6
Changes
|
|
@ -15,14 +15,20 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
|||
|
||||
* Verilator 3.921 devel
|
||||
|
||||
** Support IEEE 1800-2017 as default language.
|
||||
|
||||
*** Support trig functions ($sin() etc), bug1281. [Patrick Stewart]
|
||||
|
||||
*** Support calling system functions as tasks, bug1285. [Joel Holdsworth]
|
||||
|
||||
*** Support assert properties, bug785, bug1290. [John Coiner, et al]
|
||||
|
||||
*** Support $writememh. [John Coiner]
|
||||
|
||||
*** Add --no-debug-leak to reduce memory use under debug. [John Coiner]
|
||||
|
||||
**** Fix severe runtime performance bug in certain foreach loops. [John Coiner]
|
||||
|
||||
**** On convergence errors, show activity. [John Coiner]
|
||||
|
||||
**** Fix GCC 8.0 issues, bug1273.
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ descriptions in the next sections for more information.
|
|||
+1800-2005ext+<ext> Use SystemVerilog 2005 with file extension <ext>
|
||||
+1800-2009ext+<ext> Use SystemVerilog 2009 with file extension <ext>
|
||||
+1800-2012ext+<ext> Use SystemVerilog 2012 with file extension <ext>
|
||||
+1800-2017ext+<ext> Use SystemVerilog 2017 with file extension <ext>
|
||||
--assert Enable all assertions
|
||||
--autoflush Flush streams after all $displays
|
||||
--bbox-sys Blackbox unknown $system calls
|
||||
|
|
@ -345,7 +346,7 @@ descriptions in the next sections for more information.
|
|||
--stats Create statistics file
|
||||
--stats-vars Provide statistics on variables
|
||||
-sv Enable SystemVerilog parsing
|
||||
+systemverilogext+<ext> Synonym for +1800-2012ext+<ext>
|
||||
+systemverilogext+<ext> Synonym for +1800-2017ext+<ext>
|
||||
--top-module <topname> Name of top level input module
|
||||
--trace Enable waveform creation
|
||||
--trace-depth <levels> Depth of tracing
|
||||
|
|
@ -412,6 +413,8 @@ with the --exe option.
|
|||
|
||||
=item +1800-2012ext+I<ext>
|
||||
|
||||
=item +1800-2017ext+I<ext>
|
||||
|
||||
Specifies the language standard to be used with a specific filename
|
||||
extension, I<ext>.
|
||||
|
||||
|
|
@ -661,7 +664,7 @@ produce more detailed messages.
|
|||
|
||||
Select the language to be used by default when first processing each
|
||||
Verilog file. The language value must be "1364-1995", "1364-2001",
|
||||
"1364-2005", "1800-2005", "1800-2009" or "1800-2012".
|
||||
"1364-2005", "1800-2005", "1800-2009", "1800-2012" or "1800-2017".
|
||||
|
||||
Any language associated with a particular file extension (see the various
|
||||
+I<lang>ext+ options) will be used in preference to the language specified
|
||||
|
|
@ -674,7 +677,7 @@ legacy mixed language designs, the various +I<lang>ext+ options should be
|
|||
used.
|
||||
|
||||
If no language is specified, either by this flag or +I<lang>ext+ options,
|
||||
then the latest SystemVerilog language (IEEE 1800-2012) is used.
|
||||
then the latest SystemVerilog language (IEEE 1800-2017) is used.
|
||||
|
||||
=item +define+I<var>=I<value>
|
||||
|
||||
|
|
@ -1152,7 +1155,7 @@ compatibility with other simulators.
|
|||
|
||||
=item +systemverilogext+I<ext>
|
||||
|
||||
A synonym for C<+1800-2012ext+>I<ext>.
|
||||
A synonym for C<+1800-2017ext+>I<ext>.
|
||||
|
||||
=item --top-module I<topname>
|
||||
|
||||
|
|
@ -2216,6 +2219,11 @@ Verilator currently has some support for SystemVerilog synthesis
|
|||
constructs. As SystemVerilog features enter common usage they are added;
|
||||
please file a bug if a feature you need is missing.
|
||||
|
||||
=head2 SystemVerilog 2017 (IEEE 1800-2017) Support
|
||||
|
||||
Verilator supports the 2017 "for" loop constructs, and several minor
|
||||
cleanups made in 1800-2017.
|
||||
|
||||
=head2 Verilog AMS Support
|
||||
|
||||
Verilator implements a very small subset of Verilog AMS (Verilog Analog and
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ sub diff_dir {
|
|||
diff_file($a,$b);
|
||||
$any = 1;
|
||||
}
|
||||
$any or warn "%Warning: No .tree files found\n";
|
||||
$any or warn ("%Warning: No .tree files found that have similar base names:\n "
|
||||
.join("\n ", sort keys %files),"\n");
|
||||
}
|
||||
|
||||
sub diff_file {
|
||||
|
|
|
|||
|
|
@ -1205,10 +1205,134 @@ IData VL_SSCANF_INX(int, const std::string& ld, const char* formatp, ...) VL_MT_
|
|||
return got;
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData ofilename, const void* memp, IData start,
|
||||
IData end) VL_MT_SAFE {
|
||||
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||
return VL_WRITEMEM_W(hex, width,depth,array_lsb,2,fnw,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilenamep, const void* memp, IData start,
|
||||
IData end) VL_MT_SAFE {
|
||||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||
std::string ofilenames(ofilenamez);
|
||||
return VL_WRITEMEM_N(hex, width,depth,array_lsb,ofilenames,memp,start,end);
|
||||
}
|
||||
|
||||
const char* memhFormat(int nBits) {
|
||||
assert((nBits >= 1) && (nBits <= 32));
|
||||
|
||||
static char buf[32];
|
||||
switch ((nBits - 1) / 4) {
|
||||
case 0: VL_SNPRINTF(buf, 32, "%%01x"); break;
|
||||
case 1: VL_SNPRINTF(buf, 32, "%%02x"); break;
|
||||
case 2: VL_SNPRINTF(buf, 32, "%%03x"); break;
|
||||
case 3: VL_SNPRINTF(buf, 32, "%%04x"); break;
|
||||
case 4: VL_SNPRINTF(buf, 32, "%%05x"); break;
|
||||
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
|
||||
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
|
||||
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
void VL_WRITEMEM_N(
|
||||
bool hex, // Hex format, else binary
|
||||
int width, // Width of each array row
|
||||
int depth, // Number of rows
|
||||
int array_lsb, // Index of first row. Valid row addresses
|
||||
// // range from array_lsb up to (array_lsb + depth - 1)
|
||||
const std::string& ofilenamep, // Output file name
|
||||
const void* memp, // Array state
|
||||
IData start, // First array row address to write
|
||||
IData end // Last address to write
|
||||
) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(!hex)) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
|
||||
"VL_WRITEMEM_N only supports hex format for now, sorry!");
|
||||
return;
|
||||
}
|
||||
FILE* fp = fopen(ofilenamep.c_str(), "w");
|
||||
if (VL_UNLIKELY(!fp)) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "", "$writemem file not found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int row_addr = start; row_addr <= end; ++row_addr) {
|
||||
if ((row_addr < array_lsb)
|
||||
|| (row_addr > array_lsb + depth - 1)) {
|
||||
vluint32_t endmax = ~0;
|
||||
if (end != endmax) {
|
||||
VL_FATAL_MT(ofilenamep.c_str(), 0, "",
|
||||
"$writemem specified address out-of-bounds");
|
||||
}
|
||||
// else, it's not an error to overflow due to end == endmax,
|
||||
// just return cleanly.
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Compute the offset into the memp array.
|
||||
int row_offset = row_addr - array_lsb;
|
||||
|
||||
if (width <= 8) {
|
||||
const CData* datap
|
||||
= &(reinterpret_cast<const CData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 16) {
|
||||
const SData* datap
|
||||
= &(reinterpret_cast<const SData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 32) {
|
||||
const IData* datap
|
||||
= &(reinterpret_cast<const IData*>(memp))[row_offset];
|
||||
fprintf(fp, memhFormat(width), VL_MASK_I(width) & *datap);
|
||||
fprintf(fp, "\n");
|
||||
} else if (width <= 64) {
|
||||
const QData* datap
|
||||
= &(reinterpret_cast<const QData*>(memp))[row_offset];
|
||||
vluint64_t value = VL_MASK_Q(width) & *datap;
|
||||
vluint32_t lo = value & 0xffffffff;
|
||||
vluint32_t hi = value >> 32;
|
||||
fprintf(fp, memhFormat(width - 32), hi);
|
||||
fprintf(fp, "%08x\n", lo);
|
||||
} else {
|
||||
WDataInP memDatap = reinterpret_cast<WDataInP>(memp);
|
||||
WDataInP datap = &memDatap[row_offset * VL_WORDS_I(width)];
|
||||
// output as a sequence of VL_WORDSIZE'd words
|
||||
// from MSB to LSB. Mask off the MSB word which could
|
||||
// contain junk above the top of valid data.
|
||||
int word_idx = ((width - 1) / VL_WORDSIZE);
|
||||
bool first = true;
|
||||
while (word_idx >= 0) {
|
||||
IData data = datap[word_idx];
|
||||
if (first) {
|
||||
data &= VL_MASK_I(width);
|
||||
int top_word_nbits = ((width - 1) & 0x1f) + 1;
|
||||
fprintf(fp, memhFormat(top_word_nbits), data);
|
||||
} else {
|
||||
fprintf(fp, "%08x", data);
|
||||
}
|
||||
|
||||
word_idx--;
|
||||
first = false;
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void VL_READMEM_Q(bool hex, int width, int depth, int array_lsb, int,
|
||||
QData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
WData fnw[2]; VL_SET_WQ(fnw, ofilename);
|
||||
return VL_READMEM_W(hex,width,depth,array_lsb,2, fnw,memp,start,end);
|
||||
return VL_READMEM_W(hex,width,depth,array_lsb,2,fnw,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
|
|
@ -1216,12 +1340,20 @@ void VL_READMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
|||
char ofilenamez[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
_VL_VINT_TO_STRING(fnwords*VL_WORDSIZE, ofilenamez, ofilenamep);
|
||||
std::string ofilenames(ofilenamez);
|
||||
return VL_READMEM_N(hex,width,depth,array_lsb,fnwords,ofilenames,memp,start,end);
|
||||
return VL_READMEM_N(hex,width,depth,array_lsb,ofilenames,memp,start,end);
|
||||
}
|
||||
|
||||
void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const std::string& ofilenamep, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
if (fnwords) {}
|
||||
void VL_READMEM_N(
|
||||
bool hex, // Hex format, else binary
|
||||
int width, // Width of each array row
|
||||
int depth, // Number of rows
|
||||
int array_lsb, // Index of first row. Valid row addresses
|
||||
// // range from array_lsb up to (array_lsb + depth - 1)
|
||||
const std::string& ofilenamep, // Input file name
|
||||
void* memp, // Array state
|
||||
IData start, // First array row address to read
|
||||
IData end // Last row address to read
|
||||
) VL_MT_SAFE {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -549,6 +549,14 @@ inline void VL_READMEM_I(bool hex, int width, int depth, int array_lsb, int fnwo
|
|||
IData ofilename, void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
VL_READMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEMEM_W(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
WDataInP ofilename, const void* memp, IData start, IData end);
|
||||
extern void VL_WRITEMEM_Q(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
QData ofilename, const void* memp, IData start, IData end);
|
||||
inline void VL_WRITEMEM_I(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
IData ofilename, const void* memp, IData start, IData end) VL_MT_SAFE {
|
||||
VL_WRITEMEM_Q(hex, width,depth,array_lsb,fnwords, ofilename,memp,start,end); }
|
||||
|
||||
extern void VL_WRITEF(const char* formatp, ...);
|
||||
extern void VL_FWRITEF(IData fpi, const char* formatp, ...);
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,12 @@ inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
|
|||
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
|
||||
|
||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb, int fnwords,
|
||||
const std::string& ofilename, void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
|
||||
const std::string& ofilename,
|
||||
void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern void VL_WRITEMEM_N(bool hex, int width, int depth, int array_lsb,
|
||||
const std::string& ofilename,
|
||||
const void* memp, IData start, IData end) VL_MT_SAFE;
|
||||
extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp, ...) VL_MT_SAFE;
|
||||
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp, ...) VL_MT_SAFE;
|
||||
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* This file contains the constant definitions, structure definitions,
|
||||
* and routine declarations used by SystemVerilog DPI.
|
||||
*
|
||||
* This file is from the SystemVerilog IEEE 1800-2012 Annex I.
|
||||
* This file is from the SystemVerilog IEEE 1800-2017 Annex I.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_SVDPI
|
||||
|
|
@ -117,7 +117,7 @@ typedef uint32_t svBitVecVal;
|
|||
/*
|
||||
* Return implementation version information string ("1800-2005" or "SV3.1a").
|
||||
*/
|
||||
XXTERN const char* svDpiVersion();
|
||||
XXTERN const char* svDpiVersion( void );
|
||||
|
||||
/* a handle to a scope (an instance of a module or interface) */
|
||||
XXTERN typedef void* svScope;
|
||||
|
|
@ -241,28 +241,28 @@ XXTERN void svGetLogicArrElem2VecVal(svLogicVecVal* d, const svOpenArrayHandle s
|
|||
XXTERN void svGetLogicArrElem3VecVal(svLogicVecVal* d, const svOpenArrayHandle s,
|
||||
int indx1, int indx2, int indx3);
|
||||
|
||||
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
XXTERN svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svBit svGetBitArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svBit svGetBitArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3);
|
||||
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
XXTERN svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...);
|
||||
XXTERN svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1);
|
||||
XXTERN svLogic svGetLogicArrElem2(const svOpenArrayHandle s, int indx1, int indx2);
|
||||
XXTERN svLogic svGetLogicArrElem3(const svOpenArrayHandle s, int indx1, int indx2,
|
||||
int indx3);
|
||||
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
...);
|
||||
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
|
||||
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1);
|
||||
XXTERN void svPutLogicArrElem2(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
int indx2);
|
||||
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
XXTERN void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1,
|
||||
int indx2, int indx3);
|
||||
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
|
||||
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
|
||||
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
XXTERN void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...);
|
||||
XXTERN void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1);
|
||||
XXTERN void svPutBitArrElem2(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
int indx2);
|
||||
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1,
|
||||
int indx2, int indx3);
|
||||
|
||||
/* Functions for working with DPI context */
|
||||
|
|
@ -273,7 +273,7 @@ XXTERN void svPutBitArrElem3(const svOpenArrayHandle d, svBit value, int indx1
|
|||
* is the scope of the function's declaration site, not call site.
|
||||
* Returns NULL if called from C code that is *not* an imported function.
|
||||
*/
|
||||
XXTERN svScope svGetScope();
|
||||
XXTERN svScope svGetScope( void );
|
||||
|
||||
/*
|
||||
* Set context for subsequent export function execution.
|
||||
|
|
@ -337,7 +337,7 @@ XXTERN int svGetCallerInfo(const char** fileName, int *lineNumber);
|
|||
* Returns 1 if the current execution thread is in the disabled state.
|
||||
* Disable protocol must be adhered to if in the disabled state.
|
||||
*/
|
||||
XXTERN int svIsDisabledState();
|
||||
XXTERN int svIsDisabledState( void );
|
||||
|
||||
/*
|
||||
* Imported functions call this API function during disable processing to
|
||||
|
|
@ -345,7 +345,7 @@ XXTERN int svIsDisabledState();
|
|||
* This function must be called before returning from an imported function that is
|
||||
* in the disabled state.
|
||||
*/
|
||||
XXTERN void svAckDisabledState();
|
||||
XXTERN void svAckDisabledState( void );
|
||||
|
||||
/*
|
||||
**********************************************************
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************************
|
||||
* vpi_user.h
|
||||
*
|
||||
* IEEE Std 1800-2012 Programming Language Interface (PLI)
|
||||
* IEEE Std 1800-2017 Programming Language Interface (PLI)
|
||||
*
|
||||
* This file contains the constant definitions, structure definitions, and
|
||||
* routine declarations used by the SystemVerilog Verification Procedural
|
||||
|
|
@ -251,7 +251,7 @@ typedef PLI_UINT32 *vpiHandle;
|
|||
#define vpiModPathOut 96 /* output terminal of a module path */
|
||||
#define vpiOperand 97 /* operand of expression */
|
||||
#define vpiPortInst 98 /* connected port instance */
|
||||
#define vpiProcess 99 /* process in module */
|
||||
#define vpiProcess 99 /* process in module, program or interface */
|
||||
#define vpiVariables 100 /* variables in module */
|
||||
#define vpiUse 101 /* usage */
|
||||
|
||||
|
|
@ -978,7 +978,7 @@ XXTERN vpiHandle vpi_handle_by_multi_index PROTO_PARAMS((vpiHandle obj,
|
|||
|
||||
/****************************** GLOBAL VARIABLES ******************************/
|
||||
|
||||
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])();
|
||||
PLI_VEXTERN PLI_DLLESPEC void (*vlog_startup_routines[])( void );
|
||||
|
||||
/* array of function pointers, last pointer should be null */
|
||||
|
||||
|
|
|
|||
|
|
@ -1980,7 +1980,7 @@ class AstNodeFTaskRef : public AstNode {
|
|||
private:
|
||||
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
||||
string m_name; // Name of variable
|
||||
string m_dotted; // Dotted part of scope to task or ""
|
||||
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
AstPackage* m_packagep; // Package hierarchy
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1025,7 +1025,7 @@ void AstVarXRef::dump(std::ostream& str) {
|
|||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
if (lvalue()) str<<" [LV] => ";
|
||||
else str<<" [RV] <- ";
|
||||
str<<dotted()<<". - ";
|
||||
str<<".="<<dotted()<<" ";
|
||||
if (inlinedDots()!="") str<<" inline.="<<inlinedDots()<<" - ";
|
||||
if (varScopep()) { varScopep()->dump(str); }
|
||||
else if (varp()) { varp()->dump(str); }
|
||||
|
|
@ -1096,7 +1096,7 @@ void AstNodeFTaskRef::dump(std::ostream& str) {
|
|||
this->AstNode::dump(str);
|
||||
if (packagep()) { str<<" pkg="<<(void*)packagep(); }
|
||||
str<<" -> ";
|
||||
if (dotted()!="") { str<<dotted()<<". - "; }
|
||||
if (dotted()!="") { str<<".="<<dotted()<<" "; }
|
||||
if (taskp()) { taskp()->dump(str); }
|
||||
else { str<<"UNLINKED"; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1486,7 +1486,7 @@ class AstVarXRef : public AstNodeVarRef {
|
|||
// A VarRef to something in another module before AstScope.
|
||||
// Includes pin on a cell, as part of a ASSIGN statement to connect I/Os until AstScope
|
||||
private:
|
||||
string m_dotted; // Scope name to connected to
|
||||
string m_dotted; // Dotted part of scope the name()'ed reference is under or ""
|
||||
string m_inlinedDots; // Dotted hierarchy flattened out
|
||||
public:
|
||||
AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue)
|
||||
|
|
@ -2775,17 +2775,16 @@ public:
|
|||
void fromp(AstNode* nodep) { setOp2p(nodep); }
|
||||
};
|
||||
|
||||
class AstReadMem : public AstNodeStmt {
|
||||
class AstNodeReadWriteMem : public AstNodeStmt {
|
||||
private:
|
||||
bool m_isHex; // readmemh, not readmemb
|
||||
public:
|
||||
AstReadMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
AstNodeReadWriteMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp,
|
||||
AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeStmt (fileline), m_isHex(hex) {
|
||||
setOp1p(filenamep); setOp2p(memp); setNOp3p(lsbp); setNOp4p(msbp);
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ReadMem)
|
||||
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
|
||||
virtual bool isGateOptimizable() const { return false; }
|
||||
virtual bool isPredictOptimizable() const { return false; }
|
||||
virtual bool isPure() const { return false; }
|
||||
|
|
@ -2793,12 +2792,35 @@ public:
|
|||
virtual bool isUnlikely() const { return true; }
|
||||
virtual V3Hash sameHash() const { return V3Hash(); }
|
||||
virtual bool same(const AstNode* samep) const {
|
||||
return isHex()==static_cast<const AstReadMem*>(samep)->isHex(); }
|
||||
return isHex()==static_cast<const AstNodeReadWriteMem*>(samep)->isHex();
|
||||
}
|
||||
bool isHex() const { return m_isHex; }
|
||||
AstNode* filenamep() const { return op1p(); }
|
||||
AstNode* memp() const { return op2p(); }
|
||||
AstNode* lsbp() const { return op3p(); }
|
||||
AstNode* msbp() const { return op4p(); }
|
||||
virtual const char* cFuncPrefixp() const = 0;
|
||||
};
|
||||
|
||||
class AstReadMem : public AstNodeReadWriteMem {
|
||||
public:
|
||||
AstReadMem(FileLine* fileline, bool hex,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeReadWriteMem(fileline, hex, filenamep, memp, lsbp, msbp)
|
||||
{ }
|
||||
ASTNODE_NODE_FUNCS(ReadMem);
|
||||
virtual string verilogKwd() const { return (isHex()?"$readmemh":"$readmemb"); }
|
||||
virtual const char* cFuncPrefixp() const { return "VL_READMEM_"; }
|
||||
};
|
||||
|
||||
class AstWriteMem : public AstNodeReadWriteMem {
|
||||
public:
|
||||
AstWriteMem(FileLine* fileline,
|
||||
AstNode* filenamep, AstNode* memp, AstNode* lsbp, AstNode* msbp)
|
||||
: AstNodeReadWriteMem(fileline, true, filenamep, memp, lsbp, msbp) { }
|
||||
ASTNODE_NODE_FUNCS(WriteMem)
|
||||
virtual string verilogKwd() const { return (isHex()?"$writememh":"$writememb"); }
|
||||
virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; }
|
||||
};
|
||||
|
||||
class AstSystemT : public AstNodeStmt {
|
||||
|
|
|
|||
|
|
@ -324,8 +324,8 @@ public:
|
|||
nodep->modep()->iterateAndNext(*this);
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep) {
|
||||
puts("VL_READMEM_");
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) {
|
||||
puts(nodep->cFuncPrefixp());
|
||||
emitIQW(nodep->filenamep());
|
||||
puts(" ("); // We take a void* rather than emitIQW(nodep->memp());
|
||||
puts(nodep->isHex()?"true":"false");
|
||||
|
|
@ -335,21 +335,24 @@ public:
|
|||
uint32_t array_lsb = 0;
|
||||
{
|
||||
const AstVarRef* varrefp = VN_CAST(nodep->memp(), VarRef);
|
||||
if (!varrefp) { nodep->v3error("Readmem loading non-variable"); }
|
||||
if (!varrefp) { nodep->v3error(nodep->verilogKwd() << " loading non-variable"); }
|
||||
else if (const AstUnpackArrayDType* adtypep = VN_CAST(varrefp->varp()->dtypeSkipRefp(), UnpackArrayDType)) {
|
||||
puts(cvtToStr(varrefp->varp()->dtypep()->arrayUnpackedElements()));
|
||||
array_lsb = adtypep->lsb();
|
||||
}
|
||||
else {
|
||||
nodep->v3error("Readmem loading other than unpacked-array variable");
|
||||
nodep->v3error(nodep->verilogKwd()
|
||||
<< " loading other than unpacked-array variable");
|
||||
}
|
||||
}
|
||||
putbs(", ");
|
||||
puts(cvtToStr(array_lsb));
|
||||
putbs(",");
|
||||
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||
checkMaxWords(nodep->filenamep());
|
||||
putbs(", ");
|
||||
if (!nodep->filenamep()->dtypep()->isString()) {
|
||||
puts(cvtToStr(nodep->filenamep()->widthWords()));
|
||||
checkMaxWords(nodep->filenamep());
|
||||
putbs(", ");
|
||||
}
|
||||
nodep->filenamep()->iterateAndNext(*this);
|
||||
putbs(", ");
|
||||
nodep->memp()->iterateAndNext(*this);
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
|
|||
if (nodep->stmtsp()) nodep->stmtsp()->iterateAndNext(*this);
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep) {
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) {
|
||||
putfs(nodep,nodep->verilogKwd());
|
||||
putbs(" (");
|
||||
if (nodep->filenamep()) nodep->filenamep()->iterateAndNext(*this);
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "V3Inst.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3String.h"
|
||||
|
||||
// CONFIG
|
||||
static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it
|
||||
|
|
@ -270,14 +271,14 @@ public:
|
|||
|
||||
class InlineRelinkVisitor : public AstNVisitor {
|
||||
private:
|
||||
typedef vl_unordered_set<string> RenamedInterfacesSet;
|
||||
typedef vl_unordered_set<string> StringSet;
|
||||
|
||||
// NODE STATE
|
||||
// Input:
|
||||
// See InlineVisitor
|
||||
|
||||
// STATE
|
||||
RenamedInterfacesSet m_renamedInterfaces; // Name of renamed interface variables
|
||||
StringSet m_renamedInterfaces; // Name of renamed interface variables
|
||||
AstNodeModule* m_modp; // Current module
|
||||
AstCell* m_cellp; // Cell being cloned
|
||||
|
||||
|
|
@ -410,9 +411,8 @@ private:
|
|||
}
|
||||
virtual void visit(AstVarXRef* nodep) {
|
||||
// Track what scope it was originally under so V3LinkDot can resolve it
|
||||
string newname = m_cellp->name();
|
||||
if (nodep->inlinedDots() != "") { newname += "." + nodep->inlinedDots(); }
|
||||
nodep->inlinedDots(newname);
|
||||
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
|
||||
nodep->inlinedDots(newdots);
|
||||
for (string tryname = nodep->dotted(); 1;) {
|
||||
if (m_renamedInterfaces.count(tryname)) {
|
||||
nodep->dotted(m_cellp->name() + "__DOT__" + nodep->dotted());
|
||||
|
|
@ -430,9 +430,8 @@ private:
|
|||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep) {
|
||||
// Track what scope it was originally under so V3LinkDot can resolve it
|
||||
string newname = m_cellp->name();
|
||||
if (nodep->inlinedDots() != "") { newname += "." + nodep->inlinedDots(); }
|
||||
nodep->inlinedDots(newname);
|
||||
string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots());
|
||||
nodep->inlinedDots(newdots);
|
||||
if (m_renamedInterfaces.count(nodep->dotted())) {
|
||||
nodep->dotted(m_cellp->name() + "__DOT__" + nodep->dotted());
|
||||
}
|
||||
|
|
@ -459,9 +458,7 @@ private:
|
|||
}
|
||||
virtual void visit(AstCoverDecl* nodep) {
|
||||
// Fix path in coverage statements
|
||||
nodep->hier(m_cellp->prettyName()
|
||||
+ (nodep->hier()!="" ? ".":"")
|
||||
+ nodep->hier());
|
||||
nodep->hier(VString::dot(m_cellp->prettyName(), ".", nodep->hier()));
|
||||
nodep->iterateChildren(*this);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) {
|
||||
|
|
@ -537,7 +534,7 @@ private:
|
|||
// this loop as it clone()s itself.
|
||||
for (AstPin* pinp = nodep->pinsp(); pinp; pinp=VN_CAST(pinp->nextp(), Pin)) {
|
||||
if (!pinp->exprp()) continue;
|
||||
V3Inst::pinReconnectSimple(pinp, nodep, m_modp, false);
|
||||
V3Inst::pinReconnectSimple(pinp, nodep, false);
|
||||
}
|
||||
|
||||
// Clone original module
|
||||
|
|
|
|||
|
|
@ -86,9 +86,9 @@ private:
|
|||
// Use user1p on the PIN to indicate we created an assign for this pin
|
||||
if (!nodep->user1SetOnce()) {
|
||||
// Simplify it
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
|
||||
// Make a ASSIGNW (expr, pin)
|
||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
// Make an ASSIGNW (expr, pin)
|
||||
AstNode* exprp = nodep->exprp()->cloneTree(false);
|
||||
if (exprp->width() != nodep->modVarp()->width())
|
||||
nodep->v3fatalSrc("Width mismatch, should have been handled in pinReconnectSimple");
|
||||
if (nodep->modVarp()->isInout()) {
|
||||
|
|
@ -133,6 +133,7 @@ private:
|
|||
}
|
||||
|
||||
// Save some time
|
||||
virtual void visit(AstNodeMath*) {}
|
||||
virtual void visit(AstNodeAssign*) {}
|
||||
virtual void visit(AstAlways*) {}
|
||||
|
||||
|
|
@ -496,7 +497,7 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
|
|
@ -573,9 +574,9 @@ public:
|
|||
//######################################################################
|
||||
// Inst class functions
|
||||
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp,
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
return InstStatic::pinReconnectSimple(pinp, cellp, modp, forTristate, alwaysCvt);
|
||||
return InstStatic::pinReconnectSimple(pinp, cellp, forTristate, alwaysCvt);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class V3Inst {
|
|||
public:
|
||||
static void instAll(AstNetlist* nodep);
|
||||
static void dearrayAll(AstNetlist* nodep);
|
||||
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp, AstNodeModule* modp,
|
||||
static AstAssignW* pinReconnectSimple(AstPin* nodep, AstCell* cellp,
|
||||
bool forTristate, bool alwaysCvt=false);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
L1800_2005,
|
||||
L1800_2009,
|
||||
L1800_2012,
|
||||
L1800_2017,
|
||||
// ***Add new elements below also***
|
||||
_ENUM_END
|
||||
};
|
||||
|
|
@ -54,12 +55,14 @@ public:
|
|||
"1364-2005",
|
||||
"1800-2005",
|
||||
"1800-2009",
|
||||
"1800-2012"
|
||||
"1800-2012",
|
||||
"1800-2017"
|
||||
};
|
||||
return names[m_e];
|
||||
};
|
||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2012); }
|
||||
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009 || m_e == L1800_2012; }
|
||||
static V3LangCode mostRecent() { return V3LangCode(L1800_2017); }
|
||||
bool systemVerilog() const { return m_e == L1800_2005 || m_e == L1800_2009
|
||||
|| m_e == L1800_2012 || m_e == L1800_2017; }
|
||||
bool legal() const { return m_e != L_ERROR; }
|
||||
//
|
||||
enum en m_e;
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@
|
|||
#include "V3Graph.h"
|
||||
#include "V3Ast.h"
|
||||
#include "V3ParseImp.h"
|
||||
#include "V3String.h"
|
||||
|
||||
//######################################################################
|
||||
// LinkDot state, as a visitor of each AstNode
|
||||
|
|
@ -1807,8 +1808,7 @@ private:
|
|||
|| VN_IS(foundp->nodep(), Module)) { // if top
|
||||
if (allowScope) {
|
||||
ok = true;
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
|
||||
m_ds.m_dotSymp = foundp;
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
// Upper AstDot visitor will handle it from here
|
||||
|
|
@ -1827,8 +1827,7 @@ private:
|
|||
if (!ifaceRefVarp) nodep->v3fatalSrc("Can't find interface var ref: "<<findName);
|
||||
//
|
||||
ok = true;
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
|
||||
m_ds.m_dotSymp = foundp;
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
UINFO(9," cell -> iface varref "<<foundp->nodep()<<endl);
|
||||
|
|
@ -1845,8 +1844,7 @@ private:
|
|||
if (!ifacerefp->ifaceViaCellp()) ifacerefp->v3fatalSrc("Unlinked interface");
|
||||
// Really this is a scope reference into an interface
|
||||
UINFO(9,"varref-ifaceref "<<m_ds.m_dotText<<" "<<nodep<<endl);
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(ifacerefp->ifaceViaCellp());
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
ok = true;
|
||||
|
|
@ -1897,8 +1895,7 @@ private:
|
|||
if (!cellp) nodep->v3fatalSrc("Modport not referenced from a cell");
|
||||
AstIface* ifacep = VN_CAST(cellp->modp(), Iface);
|
||||
//string cellName = m_ds.m_dotText; // Use cellp->name
|
||||
if (m_ds.m_dotText!="") m_ds.m_dotText += ".";
|
||||
m_ds.m_dotText += nodep->name();
|
||||
m_ds.m_dotText = VString::dot(m_ds.m_dotText, ".", nodep->name());
|
||||
m_ds.m_dotSymp = m_statep->getNodeSym(modportp);
|
||||
m_ds.m_dotPos = DP_SCOPE;
|
||||
ok = true;
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ private:
|
|||
FileLine* fl = varsp->fileline();
|
||||
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
|
||||
varsp->name(), nodep->findSigned32DType());
|
||||
// These will be the left and right dimensions of the array:
|
||||
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
|
||||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension));
|
||||
|
|
@ -347,19 +348,26 @@ private:
|
|||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension));
|
||||
AstNode* stmtsp = varp;
|
||||
stmtsp->addNext(new AstAssign(fl, new AstVarRef(fl, varp->name(), true), leftp));
|
||||
AstNode* comparep =
|
||||
new AstCond(fl, new AstLte(fl, leftp->cloneTree(true), rightp->cloneTree(true)),
|
||||
// left increments up to right
|
||||
new AstLte(fl, new AstVarRef(fl, varp->name(), false), rightp->cloneTree(true)),
|
||||
// left decrements down to right
|
||||
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
|
||||
AstNode* incp =
|
||||
new AstAssign(fl, new AstVarRef(fl, varp->name(), true),
|
||||
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
|
||||
new AstNegate(fl, new AstAttrOf(fl, AstAttrType::DIM_INCREMENT,
|
||||
new AstVarRef(fl, arrayp->name(), false),
|
||||
new AstConst(fl, dimension)))));
|
||||
// Assign left-dimension into the loop var:
|
||||
stmtsp->addNext(new AstAssign
|
||||
(fl, new AstVarRef(fl, varp->name(), true), leftp));
|
||||
// This will turn into a bool constant, indicating whether
|
||||
// we count the loop variable up or down:
|
||||
AstNode* countupp = new AstLte(fl, leftp->cloneTree(true),
|
||||
rightp->cloneTree(true));
|
||||
AstNode* comparep = new AstCond(
|
||||
fl, countupp->cloneTree(true),
|
||||
// Left increments up to right
|
||||
new AstLte(fl, new AstVarRef(fl, varp->name(), false),
|
||||
rightp->cloneTree(true)),
|
||||
// Left decrements down to right
|
||||
new AstGte(fl, new AstVarRef(fl, varp->name(), false), rightp));
|
||||
AstNode* incp = new AstAssign(
|
||||
fl, new AstVarRef(fl, varp->name(), true),
|
||||
new AstAdd(fl, new AstVarRef(fl, varp->name(), false),
|
||||
new AstCond(fl, countupp,
|
||||
new AstConst(fl, 1),
|
||||
new AstConst(fl, -1))));
|
||||
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
|
||||
newp = new AstBegin(nodep->fileline(),"",stmtsp);
|
||||
dimension--;
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ V3Number::V3Number (FileLine* fileline, const char* sourcep) {
|
|||
if (!m_sized) {
|
||||
static int warned = false;
|
||||
if (!warned++) {
|
||||
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2012 5.7.1)");
|
||||
m_fileline->v3error("As that number was unsized ('d...) it is limited to 32 bits (IEEE 2017 5.7.1)");
|
||||
}
|
||||
}
|
||||
while (*(cp+1)) cp++; // Skip ahead so don't get multiple warnings
|
||||
|
|
|
|||
|
|
@ -604,7 +604,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
|||
else if ( !strncmp (sw, "+incdir+", 8)) {
|
||||
addIncDirUser (parseFileArg(optdir, string (sw+strlen("+incdir+"))));
|
||||
}
|
||||
else if (parseLangExt(sw, "+systemverilogext+", V3LangCode::L1800_2012)
|
||||
else if (parseLangExt(sw, "+systemverilogext+", V3LangCode::L1800_2017)
|
||||
|| parseLangExt(sw, "+verilog1995ext+", V3LangCode::L1364_1995)
|
||||
|| parseLangExt(sw, "+verilog2001ext+", V3LangCode::L1364_2001)
|
||||
|| parseLangExt(sw, "+1364-1995ext+", V3LangCode::L1364_1995)
|
||||
|
|
@ -612,7 +612,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
|||
|| parseLangExt(sw, "+1364-2005ext+", V3LangCode::L1364_2005)
|
||||
|| parseLangExt(sw, "+1800-2005ext+", V3LangCode::L1800_2005)
|
||||
|| parseLangExt(sw, "+1800-2009ext+", V3LangCode::L1800_2009)
|
||||
|| parseLangExt(sw, "+1800-2012ext+", V3LangCode::L1800_2012)) {
|
||||
|| parseLangExt(sw, "+1800-2012ext+", V3LangCode::L1800_2012)
|
||||
|| parseLangExt(sw, "+1800-2017ext+", V3LangCode::L1800_2017)) {
|
||||
// Nothing to do here - all done in the test
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include VL_INCLUDE_UNORDERED_MAP
|
||||
#include VL_INCLUDE_UNORDERED_SET
|
||||
|
||||
#include "V3Global.h"
|
||||
#include "V3Scope.h"
|
||||
|
|
@ -50,9 +52,9 @@ private:
|
|||
AstUser2InUse m_inuser2;
|
||||
|
||||
// TYPES
|
||||
typedef std::map<AstPackage*, AstScope*> PackageScopeMap;
|
||||
typedef std::map<std::pair<AstVar*, AstScope*>, AstVarScope*> VarScopeMap;
|
||||
typedef std::set<std::pair<AstVarRef*, AstScope*> > VarRefScopeSet;
|
||||
typedef vl_unordered_map<AstPackage*, AstScope*> PackageScopeMap;
|
||||
typedef vl_unordered_map<std::pair<AstVar*, AstScope*>, AstVarScope*> VarScopeMap;
|
||||
typedef vl_unordered_set<std::pair<AstVarRef*, AstScope*> > VarRefScopeSet;
|
||||
|
||||
// STATE, inside processing a single module
|
||||
AstNodeModule* m_modp; // Current module
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ bool VString::wildmatch(const char* s, const char* p) {
|
|||
return (*s == '\0');
|
||||
}
|
||||
|
||||
string VString::dot(const string& a, const string& dot, const string& b) {
|
||||
if (b=="") return a;
|
||||
if (a=="") return b;
|
||||
return a+dot+b;
|
||||
}
|
||||
|
||||
string VString::downcase(const string& str) {
|
||||
string out = str;
|
||||
for (string::iterator pos = out.begin(); pos != out.end(); ++pos) {
|
||||
|
|
|
|||
|
|
@ -33,8 +33,13 @@ class VString {
|
|||
static bool wildmatchi(const char* s, const char* p);
|
||||
public:
|
||||
// METHODS (generic string utilities)
|
||||
// Return true if p with ? or *'s matches s
|
||||
static bool wildmatch(const char* s, const char* p);
|
||||
// Return {a}{dot}{b}, omitting dot if a or b are empty
|
||||
static string dot(const string& a, const string& dot, const string& b);
|
||||
// Convert string to lowercase
|
||||
static string downcase(const string& str);
|
||||
// Replace any %'s with %%
|
||||
static string quotePercent(const string& str);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
os<<indent<<"+ "<<std::left<<std::setw(30)<<(searchName==""?"\"\"":searchName)<<std::setw(0)<<std::right;
|
||||
os<<" se"<<(void*)(this)<<std::setw(0);
|
||||
os<<" fallb=se"<<(void*)(m_fallbackp);
|
||||
if (m_symPrefix!="") os<<" symPrefix="<<m_symPrefix;
|
||||
os<<" n="<<nodep();
|
||||
os<<endl;
|
||||
if (doneSymsr.find(this) != doneSymsr.end()) {
|
||||
|
|
|
|||
|
|
@ -928,7 +928,7 @@ private:
|
|||
&& portp->dtypep()->basicp()
|
||||
&& portp->dtypep()->basicp()->keyword().isDpiUnreturnable()) {
|
||||
portp->v3error("DPI function may not return type "<<portp->basicp()->prettyTypeName()
|
||||
<<" (IEEE 2012 35.5.5)");
|
||||
<<" (IEEE 2017 35.5.5)");
|
||||
}
|
||||
portp->unlinkFrBack();
|
||||
rtnvarp = portp;
|
||||
|
|
|
|||
|
|
@ -1066,7 +1066,7 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||
if (!enModVarp) {
|
||||
if (nodep->exprp()) {
|
||||
// May have an output only that later connects to a tristate, so simplify now.
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, false);
|
||||
V3Inst::pinReconnectSimple(nodep, m_cellp, false);
|
||||
}
|
||||
iteratePinGuts(nodep);
|
||||
return; // No __en signals on this pin
|
||||
|
|
@ -1092,7 +1092,7 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||
} else if (inDeclProcessing) { // Not an input that was a converted tristate
|
||||
// Input only may have driver in underneath module which would stomp
|
||||
// the input value. So make a temporary connection.
|
||||
AstAssignW* reAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true, true);
|
||||
AstAssignW* reAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true, true);
|
||||
UINFO(5,"Input pin buffering: "<<reAssignp<<endl);
|
||||
m_tgraph.setTristate(reAssignp->lhsp());
|
||||
}
|
||||
|
|
@ -1146,7 +1146,7 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||
TristatePinVisitor visitor (outexprp, m_tgraph, true);
|
||||
}
|
||||
if (debug()>=9) outpinp->dumpTree(cout,"-pin-opr: ");
|
||||
outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, m_modp, true); // Note may change outpinp->exprp()
|
||||
outAssignp = V3Inst::pinReconnectSimple(outpinp, m_cellp, true); // Note may change outpinp->exprp()
|
||||
if (debug()>=9) outpinp->dumpTree(cout,"-pin-out: ");
|
||||
if (debug()>=9 && outAssignp) outAssignp->dumpTree(cout,"-pin-out: ");
|
||||
// Must still iterate the outAssignp, as need to build output equation
|
||||
|
|
@ -1154,7 +1154,7 @@ class TristateVisitor : public TristateBaseVisitor {
|
|||
|
||||
// Existing pin becomes an input, and we mark each resulting signal as tristate
|
||||
TristatePinVisitor visitor (nodep->exprp(), m_tgraph, false);
|
||||
AstNode* inAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, m_modp, true); // Note may change nodep->exprp()
|
||||
AstNode* inAssignp = V3Inst::pinReconnectSimple(nodep, m_cellp, true); // Note may change nodep->exprp()
|
||||
if (debug()>=9) nodep->dumpTree(cout,"-pin-in: ");
|
||||
if (debug()>=9 && inAssignp) inAssignp->dumpTree(cout,"-pin-as: ");
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
// V3Width's Transformations:
|
||||
// Top down traversal:
|
||||
// Determine width of sub-expressions
|
||||
// width() = # bits upper expression wants, 0 for anything-goes
|
||||
// width() = # bits upper expression wants, 0 for anything-goes
|
||||
// widthUnsized() = # bits for unsized constant, or 0 if it's sized
|
||||
// widthMin() = Alternative acceptable width for linting, or width() if sized
|
||||
// Determine this subop's width, can be either:
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
// Pass up:
|
||||
// width() = # bits this expression generates
|
||||
// widthSized() = true if all constants sized, else false
|
||||
// Compute size of this expression
|
||||
// Compute size of this expression
|
||||
// Lint warn about mismatches
|
||||
// If expr size != subop fixed, bad
|
||||
// If expr size < subop unsized minimum, bad
|
||||
|
|
@ -446,7 +446,7 @@ private:
|
|||
if (!constp) { nodep->v3error("Replication value isn't a constant."); return; }
|
||||
uint32_t times = constp->toUInt();
|
||||
if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up.
|
||||
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)"); times=1;
|
||||
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2017 11.4.12.1)"); times=1;
|
||||
}
|
||||
if (nodep->lhsp()->isString()) {
|
||||
AstNode* newp = new AstReplicateN(nodep->fileline(),nodep->lhsp()->unlinkFrBack(),
|
||||
|
|
@ -477,7 +477,7 @@ private:
|
|||
if (!constp) { nodep->v3error("Replication value isn't a constant."); return; }
|
||||
uint32_t times = constp->toUInt();
|
||||
if (times==0 && !VN_IS(nodep->backp(), Concat)) { // Concat Visitor will clean it up.
|
||||
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2012 11.4.12.1)");
|
||||
nodep->v3error("Replication value of 0 is only legal under a concatenation (IEEE 2017 11.4.12.1)");
|
||||
}
|
||||
nodep->dtypeSetString();
|
||||
}
|
||||
|
|
@ -1299,7 +1299,7 @@ private:
|
|||
}
|
||||
if (!itemp->valuep()) {
|
||||
if (num.isEqZero() && itemp != nodep->itemsp())
|
||||
itemp->v3error("Enum value illegally wrapped around (IEEE 2012 6.19)");
|
||||
itemp->v3error("Enum value illegally wrapped around (IEEE 2017 6.19)");
|
||||
if (!nodep->dtypep()->basicp()
|
||||
&& !nodep->dtypep()->basicp()->keyword().isIntNumeric()) {
|
||||
itemp->v3error("Enum names without values only allowed on numeric types");
|
||||
|
|
@ -2206,12 +2206,13 @@ private:
|
|||
assertAtStatement(nodep);
|
||||
userIterateAndNext(nodep->lhsp(), WidthVP(SELF,BOTH).p());
|
||||
}
|
||||
virtual void visit(AstReadMem* nodep) {
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) {
|
||||
assertAtStatement(nodep);
|
||||
userIterateAndNext(nodep->filenamep(), WidthVP(SELF,BOTH).p());
|
||||
userIterateAndNext(nodep->memp(), WidthVP(SELF,BOTH).p());
|
||||
if (!VN_IS(nodep->memp()->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
nodep->memp()->v3error("Unsupported: $readmem into other than unpacked array");
|
||||
nodep->memp()->v3error("Unsupported: " << nodep->verilogKwd()
|
||||
<< " into other than unpacked array");
|
||||
}
|
||||
userIterateAndNext(nodep->lsbp(), WidthVP(SELF,BOTH).p());
|
||||
userIterateAndNext(nodep->msbp(), WidthVP(SELF,BOTH).p());
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
extern void yyerror(const char*);
|
||||
extern void yyerrorf(const char* format, ...);
|
||||
|
||||
#define STATE_VERILOG_RECENT S12 // State name for most recent Verilog Version
|
||||
#define STATE_VERILOG_RECENT S17 // State name for most recent Verilog Version
|
||||
|
||||
#define PARSEP V3ParseImp::parsep()
|
||||
#define SYMP PARSEP->symp()
|
||||
|
|
@ -126,7 +126,7 @@ void yyerror(const char* errmsg) {
|
|||
static int warned = false;
|
||||
if (!warned++) {
|
||||
PARSEP->fileline()->v3error("Perhaps '"+*PARSEP->prevBisonVal().strp
|
||||
+"' is a package which needs to be predeclared? (IEEE 2012 26.3)");
|
||||
+"' is a package which needs to be predeclared? (IEEE 2017 26.3)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ void yyerrorf(const char* format, ...) {
|
|||
%a 15000
|
||||
%o 25000
|
||||
|
||||
%s V95 V01 V05 S05 S09 S12
|
||||
%s V95 V01 V05 S05 S09 S12 S17
|
||||
%s STRING ATTRMODE TABLE
|
||||
%s VA5 SAX VLT
|
||||
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
|
||||
|
|
@ -200,7 +200,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
|
||||
/************************************************************************/
|
||||
/* Verilog 1995 */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
{ws} { } /* otherwise ignore white-space */
|
||||
{crnl} { NEXTLINE(); } /* Count line numbers */
|
||||
/* Extensions to Verilog set, some specified by PSL */
|
||||
|
|
@ -269,6 +269,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"$value$plusargs" { FL; return yD_VALUEPLUSARGS; }
|
||||
"$width" { FL; return yaTIMINGSPEC; }
|
||||
"$write" { FL; return yD_WRITE; }
|
||||
"$writememh" { FL; return yD_WRITEMEMH; }
|
||||
/* Keywords */
|
||||
"always" { FL; return yALWAYS; }
|
||||
"and" { FL; return yAND; }
|
||||
|
|
@ -389,7 +390,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* Verilog 2001 */
|
||||
<V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
/* System Tasks */
|
||||
"$signed" { FL; return yD_SIGNED; }
|
||||
"$unsigned" { FL; return yD_UNSIGNED; }
|
||||
|
|
@ -420,13 +421,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* Verilog 2005 */
|
||||
<V05,S05,S09,S12,SAX>{
|
||||
<V05,S05,S09,S12,S17,SAX>{
|
||||
/* Keywords */
|
||||
"uwire" { FL; return yWIRE; }
|
||||
}
|
||||
|
||||
/* System Verilog 2005 */
|
||||
<S05,S09,S12,SAX>{
|
||||
<S05,S09,S12,S17,SAX>{
|
||||
/* System Tasks */
|
||||
"$bits" { FL; return yD_BITS; }
|
||||
"$clog2" { FL; return yD_CLOG2; }
|
||||
|
|
@ -551,7 +552,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* SystemVerilog 2009 */
|
||||
<S09,S12,SAX>{
|
||||
<S09,S12,S17,SAX>{
|
||||
/* Keywords */
|
||||
"global" { FL; return yGLOBAL__LEX; }
|
||||
"unique0" { FL; return yUNIQUE0; }
|
||||
|
|
@ -580,7 +581,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* System Verilog 2012 */
|
||||
<S12,SAX>{
|
||||
<S12,S17,SAX>{
|
||||
/* Keywords */
|
||||
"implements" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
|
||||
"interconnect" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
|
||||
|
|
@ -588,8 +589,11 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"soft" { yyerrorf("Unsupported: SystemVerilog 2012 reserved word not implemented: %s",yytext); }
|
||||
}
|
||||
|
||||
/* System Verilog 2017 */
|
||||
/* No new keywords */
|
||||
|
||||
/* Default PLI rule */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"$"[a-zA-Z_$][a-zA-Z0-9_$]* { string str (yytext,yyleng);
|
||||
yylval.strp = PARSEP->newString(AstNode::encodeName(str));
|
||||
// Lookup unencoded name including the $, to avoid hitting normal signals
|
||||
|
|
@ -696,7 +700,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/* Meta comments */
|
||||
|
||||
/* Converted from //{cmt}verilator ...{cmt} by preprocessor */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */
|
||||
"/*verilator clock_enable*/" { FL; return yVL_CLOCK_ENABLE; }
|
||||
"/*verilator coverage_block_off*/" { FL; return yVL_COVERAGE_BLOCK_OFF; }
|
||||
|
|
@ -734,7 +738,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/************************************************************************/
|
||||
|
||||
/* Single character operator thingies */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"{" { FL; return yytext[0]; }
|
||||
"}" { FL; return yytext[0]; }
|
||||
"!" { FL; return yytext[0]; }
|
||||
|
|
@ -768,7 +772,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/* Operators and multi-character symbols */
|
||||
|
||||
/* Verilog 1995 Operators */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"&&" { FL; return yP_ANDAND; }
|
||||
"||" { FL; return yP_OROR; }
|
||||
"<=" { FL; return yP_LTE; }
|
||||
|
|
@ -790,7 +794,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* Verilog 2001 Operators */
|
||||
<V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"<<<" { FL; return yP_SLEFT; }
|
||||
">>>" { FL; return yP_SSRIGHT; }
|
||||
"**" { FL; return yP_POW; }
|
||||
|
|
@ -803,7 +807,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* SystemVerilog Operators */
|
||||
<S05,S09,S12,SAX>{
|
||||
<S05,S09,S12,S17,SAX>{
|
||||
"'" { FL; return yP_TICK; }
|
||||
"'{" { FL; return yP_TICKBRA; }
|
||||
"==?" { FL; return yP_WILDEQUAL; }
|
||||
|
|
@ -837,7 +841,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
}
|
||||
|
||||
/* Identifiers and numbers */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT>{
|
||||
{escid} { FL; yylval.strp = PARSEP->newString
|
||||
(AstNode::encodeName(string(yytext+1))); // +1 to skip the backslash
|
||||
return yaID__LEX;
|
||||
|
|
@ -910,7 +914,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/************************************************************************/
|
||||
/* Attributes */
|
||||
/* Note simulators vary in support for "(* /_*something*_/ foo*)" where _ doesn't exist */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX>{
|
||||
"(*"({ws}|{crnl})*({id}|{escid}) { yymore(); yy_push_state(ATTRMODE); } /* Doesn't match (*), but (* attr_spec */
|
||||
}
|
||||
|
||||
|
|
@ -927,7 +931,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/* Preprocessor */
|
||||
/* Common for all SYSC header states */
|
||||
/* OPTIMIZE: we return one per line, make it one for the entire block */
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT,SYSCHDR,SYSCINT,SYSCIMP,SYSCIMPH,SYSCCTOR,SYSCDTOR,IGNORE>{
|
||||
"`accelerate" { } // Verilog-XL compatibility
|
||||
"`autoexpand_vectornets" { } // Verilog-XL compatibility
|
||||
"`celldefine" { PARSEP->inCellDefine(true); }
|
||||
|
|
@ -971,6 +975,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"`begin_keywords"[ \t]*\"1800-2005\" { yy_push_state(S05); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800-2009\" { yy_push_state(S09); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800-2012\" { yy_push_state(S12); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800-2017\" { yy_push_state(S17); PARSEP->pushBeginKeywords(YY_START); }
|
||||
"`begin_keywords"[ \t]*\"1800[+]VAMS\" { yy_push_state(SAX); PARSEP->pushBeginKeywords(YY_START); } /*Latest SV*/
|
||||
"`end_keywords" { yy_pop_state(); if (!PARSEP->popBeginKeywords()) yyerrorf("`end_keywords when not inside `begin_keywords block"); }
|
||||
|
||||
|
|
@ -1002,7 +1007,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
/************************************************************************/
|
||||
/* Default rules - leave last */
|
||||
|
||||
<V95,V01,V05,VA5,S05,S09,S12,SAX,VLT>{
|
||||
<V95,V01,V05,VA5,S05,S09,S12,S17,SAX,VLT>{
|
||||
"`"[a-zA-Z_0-9]+ { FL; yyerrorf("Define or directive not defined: %s",yytext); }
|
||||
"//"[^\n]* { } /* throw away single line comments */
|
||||
. { FL; return yytext[0]; } /* return single char ops. */
|
||||
|
|
|
|||
|
|
@ -515,6 +515,7 @@ class AstSenTree;
|
|||
%token<fl> yD_VALUEPLUSARGS "$value$plusargs"
|
||||
%token<fl> yD_WARNING "$warning"
|
||||
%token<fl> yD_WRITE "$write"
|
||||
%token<fl> yD_WRITEMEMH "$writememh"
|
||||
|
||||
%token<fl> yVL_CLOCK "/*verilator sc_clock*/"
|
||||
%token<fl> yVL_CLOCKER "/*verilator clocker*/"
|
||||
|
|
@ -742,7 +743,6 @@ package_or_generate_item_declaration<nodep>: // ==IEEE: package_or_generate_item
|
|||
| local_parameter_declaration ';' { $$ = $1; }
|
||||
| parameter_declaration ';' { $$ = $1; }
|
||||
//UNSUP covergroup_declaration { $$ = $1; }
|
||||
//UNSUP overload_declaration { $$ = $1; }
|
||||
//UNSUP assertion_item_declaration { $$ = $1; }
|
||||
| ';' { $$ = NULL; }
|
||||
;
|
||||
|
|
@ -2277,7 +2277,6 @@ block_item_declaration<nodep>: // ==IEEE: block_item_declaration
|
|||
data_declaration { $$ = $1; }
|
||||
| local_parameter_declaration ';' { $$ = $1; }
|
||||
| parameter_declaration ';' { $$ = $1; }
|
||||
//UNSUP overload_declaration { $$ = $1; }
|
||||
//UNSUP let_declaration { $$ = $1; }
|
||||
;
|
||||
|
||||
|
|
@ -2376,8 +2375,7 @@ statement_item<nodep>: // IEEE: statement_item
|
|||
| yREPEAT '(' expr ')' stmtBlock { $$ = new AstRepeat($1,$3,$5);}
|
||||
| yWHILE '(' expr ')' stmtBlock { $$ = new AstWhile($1,$3,$5);}
|
||||
// // for's first ';' is in for_initalization
|
||||
| yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
|
||||
{ $$ = new AstBegin($1,"",$3); $3->addNext(new AstWhile($1, $4,$8,$6)); }
|
||||
| statementFor { $$ = $1; }
|
||||
| yDO stmtBlock yWHILE '(' expr ')' ';' { if ($2) {
|
||||
$$ = $2->cloneTree(true);
|
||||
$$->addNext(new AstWhile($1,$5,$2));
|
||||
|
|
@ -2429,6 +2427,15 @@ statement_item<nodep>: // IEEE: statement_item
|
|||
| error ';' { $$ = NULL; }
|
||||
;
|
||||
|
||||
statementFor<beginp>: // IEEE: part of statement
|
||||
yFOR '(' for_initialization expr ';' for_stepE ')' stmtBlock
|
||||
{ $$ = new AstBegin($1,"",$3);
|
||||
$$->addStmtsp(new AstWhile($1, $4,$8,$6)); }
|
||||
| yFOR '(' for_initialization ';' for_stepE ')' stmtBlock
|
||||
{ $$ = new AstBegin($1,"",$3);
|
||||
$$->addStmtsp(new AstWhile($1, new AstConst($1,AstConst::LogicTrue()),$7,$5)); }
|
||||
;
|
||||
|
||||
statementVerilatorPragmas<nodep>:
|
||||
yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
|
||||
;
|
||||
|
|
@ -2603,6 +2610,7 @@ for_initialization<nodep>: // ==IEEE: for_initialization + for_variable_declarat
|
|||
$$ = VARDONEA($<fl>2,*$2,NULL,NULL);
|
||||
$$->addNext(new AstAssign($3,new AstVarRef($3,*$2,true),$4));}
|
||||
| varRefBase '=' expr ';' { $$ = new AstAssign($2,$1,$3); }
|
||||
| ';' { $$ = NULL; }
|
||||
//UNSUP: List of initializations
|
||||
;
|
||||
|
||||
|
|
@ -2707,6 +2715,10 @@ system_t_call<nodep>: // IEEE: system_tf_call (as task)
|
|||
| yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); }
|
||||
| yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); }
|
||||
//
|
||||
| yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1,$3,$5,NULL,NULL); }
|
||||
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,NULL); }
|
||||
| yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1,$3,$5,$7,$9); }
|
||||
//
|
||||
// Any system function as a task
|
||||
| system_f_call_or_t { $$ = new AstSysFuncAsTask($<fl>1, $1); }
|
||||
;
|
||||
|
|
@ -3122,7 +3134,7 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
|
|||
//
|
||||
// // IEEE: "... hierarchical_identifier select" see below
|
||||
//
|
||||
// // IEEE: empty_queue
|
||||
// // IEEE: empty_queue (IEEE 1800-2017 empty_unpacked_array_concatenation)
|
||||
//UNSUP '{' '}'
|
||||
//
|
||||
// // IEEE: concatenation/constant_concatenation
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ compile (
|
|||
v_flags2 => ["--lint-only"],
|
||||
fails=>$Self->{v3},
|
||||
expect=>
|
||||
'%Error: t/t_dpi_logic_bad.v:\d+: DPI function may not return type BASICDTYPE \'logic\' \(IEEE 2012 35.5.5\)
|
||||
'%Error: t/t_dpi_logic_bad.v:\d+: DPI function may not return type BASICDTYPE \'logic\' \(IEEE 2017 35.5.5\)
|
||||
%Error: Exiting due to .*'
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,22 @@ module t (/*AUTOARG*/
|
|||
if (i !== -1) $stop;
|
||||
if (loops !== 17) $stop;
|
||||
//
|
||||
// 1800-2017 optionals init/expr/incr
|
||||
loops = 0;
|
||||
i = 0;
|
||||
for (; i<10; ++i) ++loops;
|
||||
if (loops !== 10) $stop;
|
||||
//
|
||||
loops = 0;
|
||||
i = 0;
|
||||
for (i=0; i<10; ) begin ++loops; ++i; end
|
||||
if (loops !== 10) $stop;
|
||||
//
|
||||
loops = 0;
|
||||
i = 0;
|
||||
for (; ; ++i) begin ++loops; break; end
|
||||
if (loops !== 1) $stop;
|
||||
//
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,11 +8,21 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
|
|||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
verilator_flags2 => ['--assert']
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
# We expect all loops should be unrolled by verilator,
|
||||
# none of the loop variables should exist in the output:
|
||||
file_grep_not ("$Self->{obj_dir}/$Self->{VM_PREFIX}.cpp", qr/index_/);
|
||||
|
||||
# Further, we expect that all logic within the loop should
|
||||
# have been evaluated inside the compiler. So there should be
|
||||
# no references to 'sum' in the .cpp.
|
||||
file_grep_not ("$Self->{obj_dir}/$Self->{VM_PREFIX}.cpp", qr/sum/);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module t (/*AUTOARG*/);
|
|||
reg [63:0] sum;
|
||||
reg [2:1] [4:3] array [5:6] [7:8];
|
||||
reg [1:2] [3:4] larray [6:5] [8:7];
|
||||
bit [31:0] depth1_array [0:0];
|
||||
|
||||
function [63:0] crc (input [63:0] sum, input [31:0] a, input [31:0] b, input [31:0] c, input [31:0] d);
|
||||
crc = {sum[62:0],sum[63]} ^ {4'b0,a[7:0], 4'h0,b[7:0], 4'h0,c[7:0], 4'h0,d[7:0]};
|
||||
|
|
@ -20,53 +21,68 @@ module t (/*AUTOARG*/);
|
|||
|
||||
initial begin
|
||||
sum = 0;
|
||||
foreach (array[a]) begin
|
||||
sum = crc(sum, a, 0, 0, 0);
|
||||
// We use 'index_' as the prefix for all loop vars,
|
||||
// this allows t_foreach.pl to confirm that all loops
|
||||
// have been unrolled and flattened away and no loop vars
|
||||
// remain in the generated .cpp
|
||||
foreach (depth1_array[index_a]) begin
|
||||
sum = crc(sum, index_a, 0, 0, 0);
|
||||
|
||||
// Ensure the index never goes out of bounds.
|
||||
// We used to get this wrong for an array of depth 1.
|
||||
assert (index_a != -1);
|
||||
assert (index_a != 1);
|
||||
end
|
||||
`checkh(sum, 64'h0);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[index_a]) begin
|
||||
sum = crc(sum, index_a, 0, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h000000c000000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b]) begin
|
||||
sum = crc(sum, a, b, 0, 0);
|
||||
foreach (array[index_a,index_b]) begin
|
||||
sum = crc(sum, index_a, index_b, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h000003601e000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b,c]) begin
|
||||
sum = crc(sum, a, b, c, 0);
|
||||
foreach (array[index_a,index_b,index_c]) begin
|
||||
sum = crc(sum, index_a, index_b, index_c, 0);
|
||||
end
|
||||
`checkh(sum, 64'h00003123fc101000);
|
||||
|
||||
sum = 0;
|
||||
foreach (array[a,b,c,d]) begin
|
||||
sum = crc(sum, a, b, c, d);
|
||||
foreach (array[index_a,index_b,index_c,index_d]) begin
|
||||
sum = crc(sum, index_a, index_b, index_c, index_d);
|
||||
end
|
||||
`checkh(sum, 64'h0030128ab2a8e557);
|
||||
|
||||
//
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a]) begin
|
||||
sum = crc(sum, a, 0, 0, 0);
|
||||
foreach (larray[index_a]) begin
|
||||
sum = crc(sum, index_a, 0, 0, 0);
|
||||
end
|
||||
`checkh(sum, 64'h0000009000000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b]) begin
|
||||
sum = crc(sum, a, b, 0, 0);
|
||||
sum = sum + {4'b0,a[7:0], 4'h0,b[7:0]};
|
||||
foreach (larray[index_a,index_b]) begin
|
||||
sum = crc(sum, index_a, index_b, 0, 0);
|
||||
sum = sum + {4'b0,index_a[7:0], 4'h0,index_b[7:0]};
|
||||
end
|
||||
`checkh(sum, 64'h000002704b057073);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b,c]) begin
|
||||
sum = crc(sum, a, b, c, 0);
|
||||
foreach (larray[index_a,index_b,index_c]) begin
|
||||
sum = crc(sum, index_a, index_b, index_c, 0);
|
||||
end
|
||||
`checkh(sum, 64'h00002136f9000000);
|
||||
|
||||
sum = 0;
|
||||
foreach (larray[a,b,c,d]) begin
|
||||
sum = crc(sum, a, b, c, d);
|
||||
foreach (larray[index_a,index_b,index_c,index_d]) begin
|
||||
sum = crc(sum, index_a, index_b, index_c, index_d);
|
||||
end
|
||||
`checkh(sum, 64'h0020179aa7aa0aaa);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ compile (
|
|||
make_main => 0,
|
||||
expect=> quotemeta(
|
||||
qq{%Error: t/t_lint_pkg_colon_bad.v:6: syntax error, unexpected ::, expecting ')' or ','
|
||||
%Error: t/t_lint_pkg_colon_bad.v:6: Perhaps 'mispkg' is a package which needs to be predeclared? (IEEE 2012 26.3)
|
||||
%Error: t/t_lint_pkg_colon_bad.v:6: Perhaps 'mispkg' is a package which needs to be predeclared? (IEEE 2017 26.3)
|
||||
%Error: t/t_lint_pkg_colon_bad.v:7: syntax error, unexpected ::, expecting ',' or ';'
|
||||
}).'%Error: Exiting due to.*'
|
||||
);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ compile (
|
|||
make_main => 0,
|
||||
expect=> quotemeta(
|
||||
qq{%Error: t/t_lint_unsized_bad.v:7: Too many digits for 32 bit number: 'd123456789123456789123456789
|
||||
%Error: t/t_lint_unsized_bad.v:7: As that number was unsized ('d...) it is limited to 32 bits (IEEE 2012 5.7.1)
|
||||
%Error: t/t_lint_unsized_bad.v:7: As that number was unsized ('d...) it is limited to 32 bits (IEEE 2017 5.7.1)
|
||||
}).'%Error: Exiting due to.*'
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ module t (/*AUTOARG*/
|
|||
if (bug764_p11 !== 4'b000x) $stop;
|
||||
if (~& bug764_p11 !== 1'b1) $stop;
|
||||
//verilator lint_on WIDTH
|
||||
// However IEEE says for constants in 2012 5.7.1 that smaller-sizes do extend
|
||||
// However IEEE 2017 5.7.1 says for constants that smaller-sizes do extend
|
||||
if (4'bx !== 4'bxxxx) $stop;
|
||||
if (4'bz !== 4'bzzzz) $stop;
|
||||
if (4'b1 !== 4'b0001) $stop;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
compile (
|
||||
);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
file_grep_not ("$Self->{obj_dir}/$Self->{VM_PREFIX}.cpp", qr/rstn_r/);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2017 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
integer cyc=0;
|
||||
reg [63:0] crc;
|
||||
reg [63:0] sum;
|
||||
|
||||
// Take CRC data and apply to testblock inputs
|
||||
wire [15:0] in = crc[15:0];
|
||||
|
||||
/*AUTOWIRE*/
|
||||
// Beginning of automatic wires (for undeclared instantiated-module outputs)
|
||||
wire out; // From test of Test.v
|
||||
// End of automatics
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.out (out),
|
||||
// Inputs
|
||||
.in (in[15:0]));
|
||||
|
||||
// Aggregate outputs into a single result vector
|
||||
wire [63:0] result = {63'h0, out};
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("[%0t] cyc==%0d crc=%x result=%x\n",$time, cyc, crc, result);
|
||||
`endif
|
||||
cyc <= cyc + 1;
|
||||
crc <= {crc[62:0], crc[63]^crc[2]^crc[0]};
|
||||
sum <= result ^ {sum[62:0],sum[63]^sum[2]^sum[0]};
|
||||
if (cyc==0) begin
|
||||
// Setup
|
||||
crc <= 64'h5aef0c8d_d70a4497;
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<10) begin
|
||||
sum <= '0;
|
||||
end
|
||||
else if (cyc<90) begin
|
||||
end
|
||||
else if (cyc==99) begin
|
||||
$write("[%0t] cyc==%0d crc=%x sum=%x\n",$time, cyc, crc, sum);
|
||||
if (crc !== 64'hc77bb9b3784ea091) $stop;
|
||||
// What checksum will we end up with (above print should match)
|
||||
`define EXPECTED_SUM 64'h162c58b1635b8d6e
|
||||
if (sum !== `EXPECTED_SUM) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Outputs
|
||||
out,
|
||||
// Inputs
|
||||
in
|
||||
);
|
||||
|
||||
input [15:0] in;
|
||||
output reg out;
|
||||
|
||||
// TODO this should flatten into a reduction OR
|
||||
always_comb begin
|
||||
out = 0;
|
||||
for (int i=0; i<16; i=i+1) begin
|
||||
if (in[i]) begin
|
||||
out = 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -14,8 +14,10 @@ module t (/*AUTOARG*/
|
|||
v05 v05 ();
|
||||
s05 s05 ();
|
||||
s09 s09 ();
|
||||
a23 a23 ();
|
||||
s12 s12 ();
|
||||
s17 s17 ();
|
||||
|
||||
a23 a23 ();
|
||||
|
||||
initial begin
|
||||
$finish;
|
||||
|
|
@ -60,6 +62,14 @@ module s12;
|
|||
endmodule
|
||||
`end_keywords
|
||||
|
||||
`begin_keywords "1800-2017"
|
||||
module s17;
|
||||
final begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
end
|
||||
endmodule
|
||||
`end_keywords
|
||||
|
||||
`begin_keywords "VAMS-2.3"
|
||||
module a23;
|
||||
real foo; initial foo = sqrt(2.0);
|
||||
|
|
|
|||
|
|
@ -10,14 +10,59 @@ module t;
|
|||
reg [5:0] binary_nostart [2:15];
|
||||
reg [5:0] binary_start [0:15];
|
||||
reg [175:0] hex [0:15];
|
||||
reg [(32*6)-1:0] hex_align [0:15];
|
||||
string fns;
|
||||
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
reg [5:0] binary_string_tmp [2:15];
|
||||
reg [5:0] binary_nostart_tmp [2:15];
|
||||
reg [5:0] binary_start_tmp [0:15];
|
||||
reg [175:0] hex_tmp [0:15];
|
||||
reg [(32*6)-1:0] hex_align_tmp [0:15];
|
||||
string fns_tmp;
|
||||
`endif
|
||||
// verilator lint_on LITENDIAN
|
||||
|
||||
integer i;
|
||||
|
||||
initial begin
|
||||
begin
|
||||
// Initialize memories to zero,
|
||||
// avoid differences between 2-state and 4-state.
|
||||
for (i=0; i<16; i=i+1) begin
|
||||
binary_start[i] = 6'h0;
|
||||
hex[i] = 176'h0;
|
||||
hex_align[i] = {32*6{1'b0}};
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
binary_start_tmp[i] = 6'h0;
|
||||
hex_tmp[i] = 176'h0;
|
||||
hex_align_tmp[i] = {32*6{1'b0}};
|
||||
`endif
|
||||
end
|
||||
for (i=2; i<16; i=i+1) begin
|
||||
binary_string[i] = 6'h0;
|
||||
binary_nostart[i] = 6'h0;
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
binary_string_tmp[i] = 6'h0;
|
||||
binary_nostart_tmp[i] = 6'h0;
|
||||
`endif
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
$readmemb("t/t_sys_readmem_b.mem", binary_nostart_tmp);
|
||||
// Do a round-trip $writememh and $readmemh cycle.
|
||||
// This covers $writememh and ensures we can read our
|
||||
// own memh output file.
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("-Writing %s", `OUT_TMP1);
|
||||
`endif
|
||||
$writememh(`OUT_TMP1, binary_nostart_tmp);
|
||||
$readmemh(`OUT_TMP1, binary_nostart);
|
||||
`else
|
||||
$readmemb("t/t_sys_readmem_b.mem", binary_nostart);
|
||||
`endif
|
||||
`ifdef TEST_VERBOSE
|
||||
for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, binary_nostart[i]);
|
||||
`endif
|
||||
|
|
@ -33,7 +78,16 @@ module t;
|
|||
end
|
||||
|
||||
begin
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
$readmemb("t/t_sys_readmem_b_8.mem", binary_start_tmp, 4, 4+7);
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("-Writing %s", `OUT_TMP2);
|
||||
`endif
|
||||
$writememh(`OUT_TMP2, binary_start_tmp, 4, 4+7);
|
||||
$readmemh(`OUT_TMP2, binary_start, 4, 4+7);
|
||||
`else
|
||||
$readmemb("t/t_sys_readmem_b_8.mem", binary_start, 4, 4+7);
|
||||
`endif
|
||||
`ifdef TEST_VERBOSE
|
||||
for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, binary_start[i]);
|
||||
`endif
|
||||
|
|
@ -48,7 +102,18 @@ module t;
|
|||
end
|
||||
|
||||
begin
|
||||
// The 'hex' array is a non-exact multiple of word size
|
||||
// (possible corner case)
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
$readmemh("t/t_sys_readmem_h.mem", hex_tmp, 0);
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("-Writing %s", `OUT_TMP3);
|
||||
`endif
|
||||
$writememh(`OUT_TMP3, hex_tmp, 0);
|
||||
$readmemh(`OUT_TMP3, hex, 0);
|
||||
`else
|
||||
$readmemh("t/t_sys_readmem_h.mem", hex, 0);
|
||||
`endif
|
||||
`ifdef TEST_VERBOSE
|
||||
for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, hex[i]);
|
||||
`endif
|
||||
|
|
@ -59,8 +124,40 @@ module t;
|
|||
end
|
||||
|
||||
begin
|
||||
string fns = "t/t_sys_readmem_b.mem";
|
||||
// The 'hex align' array is similar to 'hex', but it is an
|
||||
// exact multiple of word size -- another possible corner case.
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
$readmemh("t/t_sys_readmem_align_h.mem", hex_align_tmp, 0);
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("-Writing %s", `OUT_TMP4);
|
||||
`endif
|
||||
$writememh(`OUT_TMP4, hex_align_tmp, 0);
|
||||
$readmemh(`OUT_TMP4, hex_align, 0);
|
||||
`else
|
||||
$readmemh("t/t_sys_readmem_align_h.mem", hex_align, 0);
|
||||
`endif
|
||||
`ifdef TEST_VERBOSE
|
||||
for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, hex_align[i]);
|
||||
`endif
|
||||
if (hex_align['h04] != 192'h77554004_37654321_27654321_17654321_07654321_abcdef10) $stop;
|
||||
if (hex_align['h0a] != 192'h7755400a_37654321_27654321_17654321_07654321_abcdef11) $stop;
|
||||
if (hex_align['h0b] != 192'h7755400b_37654321_27654321_17654321_07654321_abcdef12) $stop;
|
||||
if (hex_align['h0c] != 192'h7755400c_37654321_27654321_17654321_07654321_abcdef13) $stop;
|
||||
end
|
||||
|
||||
begin
|
||||
fns = "t/t_sys_readmem_b.mem";
|
||||
`ifdef WRITEMEM_READ_BACK
|
||||
fns_tmp = `OUT_TMP5;
|
||||
$readmemb(fns, binary_string_tmp);
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("-Writing %s", `OUT_TMP5);
|
||||
`endif
|
||||
$writememh(fns_tmp, binary_string_tmp);
|
||||
$readmemh(fns_tmp, binary_string);
|
||||
`else
|
||||
$readmemb(fns, binary_string);
|
||||
`endif
|
||||
`ifdef TEST_VERBOSE
|
||||
for (i=0; i<16; i=i+1) $write(" @%x = %x\n", i, binary_string[i]);
|
||||
`endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test data file
|
||||
//
|
||||
// Copyright 2006 by Wilson Snyder. This program is free software; you can
|
||||
// redistribute it and/or modify it under the terms of either the GNU
|
||||
// Lesser General Public License Version 3 or the Perl Artistic License
|
||||
// Version 2.0.
|
||||
|
||||
@4
|
||||
77554004_37654321_27654321_17654321_07654321_abcdef10
|
||||
@a
|
||||
7755400a_37654321_27654321_17654321_07654321_abcdef11
|
||||
7755400b_37654321_27654321_17654321_07654321_abcdef12
|
||||
7755400c_37654321_27654321_17654321_07654321_abcdef13
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
02
|
||||
03
|
||||
04
|
||||
05
|
||||
06
|
||||
07
|
||||
10
|
||||
00
|
||||
00
|
||||
00
|
||||
14
|
||||
15
|
||||
00
|
||||
00
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
10
|
||||
11
|
||||
12
|
||||
13
|
||||
14
|
||||
15
|
||||
16
|
||||
17
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
400437654321276543211765432107654321abcdef10
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
400a37654321276543211765432107654321abcdef11
|
||||
400b37654321276543211765432107654321abcdef12
|
||||
400c37654321276543211765432107654321abcdef13
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
7755400437654321276543211765432107654321abcdef10
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
7755400a37654321276543211765432107654321abcdef11
|
||||
7755400b37654321276543211765432107654321abcdef12
|
||||
7755400c37654321276543211765432107654321abcdef13
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
02
|
||||
03
|
||||
04
|
||||
05
|
||||
06
|
||||
07
|
||||
10
|
||||
00
|
||||
00
|
||||
00
|
||||
14
|
||||
15
|
||||
00
|
||||
00
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you can
|
||||
# redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
|
||||
top_filename("t/t_sys_readmem.v");
|
||||
|
||||
# Use random reset to ensure we're fully initializing arrays before
|
||||
# $writememh, to avoid miscompares with X's on 4-state simulators.
|
||||
$Self->{verilated_randReset} = 2; # 2 == truly random
|
||||
|
||||
compile(v_flags2 => [
|
||||
"+define+WRITEMEM_READ_BACK=1",
|
||||
"+define+OUT_TMP1=\\\"$Self->{obj_dir}/tmp1.mem\\\"",
|
||||
"+define+OUT_TMP2=\\\"$Self->{obj_dir}/tmp2.mem\\\"",
|
||||
"+define+OUT_TMP3=\\\"$Self->{obj_dir}/tmp3.mem\\\"",
|
||||
"+define+OUT_TMP4=\\\"$Self->{obj_dir}/tmp4.mem\\\"",
|
||||
"+define+OUT_TMP5=\\\"$Self->{obj_dir}/tmp5.mem\\\"",
|
||||
]);
|
||||
|
||||
execute (
|
||||
check_finished=>1,
|
||||
);
|
||||
|
||||
for (my $i = 1; $i <= 5; $i++) {
|
||||
my $gold = "$Self->{t_dir}/t_sys_writemem.gold${i}.mem";
|
||||
my $out = "$Self->{obj_dir}/tmp${i}.mem";
|
||||
print "> diff $gold $out\n";
|
||||
my @diffs = `diff $gold $out`;
|
||||
if (0 < scalar @diffs) {
|
||||
print @diffs;
|
||||
$Self->error("Got unexpected diffs against gold.");
|
||||
}
|
||||
}
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -2,11 +2,11 @@
|
|||
<!-- DESCRIPTION: Verilator output: XML representation of netlist -->
|
||||
<verilator_xml>
|
||||
<files>
|
||||
<file id="a" filename="AstRoot" language="1800-2012"/>
|
||||
<file id="b" filename="COMMAND_LINE" language="1800-2012"/>
|
||||
<file id="c" filename="INTERNAL_VERILATOR_DEFINE" language="1800-2012"/>
|
||||
<file id="d" filename="input.vc" language="1800-2012"/>
|
||||
<file id="e" filename="t/t_xml_first.v" language="1800-2012"/>
|
||||
<file id="a" filename="AstRoot" language="1800-2017"/>
|
||||
<file id="b" filename="COMMAND_LINE" language="1800-2017"/>
|
||||
<file id="c" filename="INTERNAL_VERILATOR_DEFINE" language="1800-2017"/>
|
||||
<file id="d" filename="input.vc" language="1800-2017"/>
|
||||
<file id="e" filename="t/t_xml_first.v" language="1800-2017"/>
|
||||
</files>
|
||||
<netlist>
|
||||
<module fl="e6" name="t" topModule="1">
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
<!-- DESCRIPTION: Verilator output: XML representation of netlist -->
|
||||
<verilator_xml>
|
||||
<files>
|
||||
<file id="a" filename="AstRoot" language="1800-2012"/>
|
||||
<file id="b" filename="COMMAND_LINE" language="1800-2012"/>
|
||||
<file id="c" filename="INTERNAL_VERILATOR_DEFINE" language="1800-2012"/>
|
||||
<file id="d" filename="input.vc" language="1800-2012"/>
|
||||
<file id="e" filename="t/t_xml_tag.v" language="1800-2012"/>
|
||||
<file id="a" filename="AstRoot" language="1800-2017"/>
|
||||
<file id="b" filename="COMMAND_LINE" language="1800-2017"/>
|
||||
<file id="c" filename="INTERNAL_VERILATOR_DEFINE" language="1800-2017"/>
|
||||
<file id="d" filename="input.vc" language="1800-2017"/>
|
||||
<file id="e" filename="t/t_xml_tag.v" language="1800-2017"/>
|
||||
</files>
|
||||
<netlist>
|
||||
<module fl="e6" name="m">
|
||||
|
|
|
|||
Loading…
Reference in New Issue