mirror of
https://github.com/verilator/verilator.git
synced 2026-10-05 17:43:31 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d4305192a | ||
|
|
9e61b9f696 | ||
|
|
491539ff32 | ||
|
|
4c29a13a6e | ||
|
|
b66e1bdb9e | ||
|
|
7312de6bc2 | ||
|
|
1d6bcda014 | ||
|
|
5a747bad7d | ||
|
|
9542783a7e | ||
|
|
a59639413d | ||
|
|
d5eb92a071 | ||
|
|
994cde57af | ||
|
|
238a5809bf | ||
|
|
49fa65c0dd | ||
|
|
49123f169c | ||
|
|
4dc64c387f | ||
|
|
98a63711dd | ||
|
|
cb95cf4745 | ||
|
|
acd48fa61d | ||
|
|
cb7abcbaea |
@@ -24,3 +24,4 @@ internals.txt
|
||||
verilator.txt
|
||||
verilator_bin*
|
||||
verilator_coverage_bin*
|
||||
verilator.pc
|
||||
|
||||
@@ -3,6 +3,31 @@ Revision history for Verilator
|
||||
The contributors that suggested a given feature are shown in []. [by ...]
|
||||
indicates the contributor was also the author of the fix; Thanks!
|
||||
|
||||
* Verilator 3.873 2015-06-06
|
||||
|
||||
*** Add pkg-config .pc file, bug919. [Stefan Wallentowitz]
|
||||
|
||||
**** Fix installing missing manpages, bug908. [Ahmed El-Mahmoudy]
|
||||
|
||||
**** Fix sign extension in large localparams, bug910. [Mike Thyer]
|
||||
|
||||
**** Fix core dump in sync-async warnings, bug911. [Sebastian Dressler]
|
||||
|
||||
**** Fix truncation warning with -pins-bv, bug912. [Alfonso Martinez]
|
||||
|
||||
**** Fix Cygwin uint32 compile, bug914. [Matthew Barr]
|
||||
|
||||
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
|
||||
|
||||
**** Fix part-select in constant function, bug916. [Andrew Bardsley]
|
||||
|
||||
**** Fix width extension on mis-width ports, bug918. [Patrick Maupin]
|
||||
|
||||
**** Fix width propagation on sized casts, bug925. [Jonathon Donaldson]
|
||||
|
||||
**** Fix MSVC++ compiler error, bug927. [Hans Tichelaar]
|
||||
|
||||
|
||||
* Verilator 3.872 2015-04-05
|
||||
|
||||
*** Add VerilatedVcdFile to allow real-time waveforms, bug890. [HyungKi Jeong]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
.*\.tex
|
||||
.*\.key
|
||||
.*\.vcd
|
||||
.*\.1
|
||||
/obj_dir/
|
||||
/obj_dbg/
|
||||
/obj_opt/
|
||||
@@ -27,6 +28,7 @@ config.cache$
|
||||
config.status$
|
||||
verilator.log
|
||||
verilator.tex
|
||||
verilator.pc$
|
||||
verilator_bin.*
|
||||
verilator_coverage_bin.*
|
||||
.vcsmx_rebuild$
|
||||
|
||||
+14
-9
@@ -84,6 +84,10 @@ infodir = @infodir@
|
||||
# Generally ${prefix}/share/verilator
|
||||
pkgdatadir = @pkgdatadir@
|
||||
|
||||
# Directory in which to install pkgconfig file
|
||||
# Generall ${prefix}/share/pkgconfig
|
||||
pkgconfigdir = @pkgconfigdir@
|
||||
|
||||
# Directory in which to install data across multiple architectures
|
||||
datarootdir = @datarootdir@
|
||||
|
||||
@@ -101,8 +105,8 @@ SHELL = /bin/sh
|
||||
SUBDIRS = src test_verilated test_c test_sc test_regress
|
||||
|
||||
INFOS = README README.html README.pdf internals.txt internals.html \
|
||||
internals.pdf verilator.txt verilator.html verilator.1 verilator.pdf \
|
||||
verilator_coverage.1
|
||||
internals.pdf verilator.txt verilator.html verilator.pdf \
|
||||
$(VL_INST_MAN_FILES)
|
||||
|
||||
# Files that can be generated, but should be up to date for a distribution.
|
||||
DISTDEP = info Makefile
|
||||
@@ -207,10 +211,7 @@ test_regress: all_nomsg
|
||||
info: $(INFOS)
|
||||
|
||||
# Use --no-split to avoid creating filenames > 14 chars.
|
||||
verilator.1: ${srcdir}/bin/verilator
|
||||
pod2man $< $@
|
||||
|
||||
verilator_coverage.1: ${srcdir}/bin/verilator_coverage
|
||||
%.1: ${srcdir}/bin/%
|
||||
pod2man $< $@
|
||||
|
||||
verilator.txt: ${srcdir}/bin/verilator
|
||||
@@ -267,7 +268,7 @@ VL_INST_BIN_FILES = verilator verilator_bin verilator_bin_dbg verilator_coverage
|
||||
# so they can be found by the user, and under $VERILATOR_ROOT.
|
||||
|
||||
# See uninstall also - don't put wildcards in this variable, it might uninstall other stuff
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1
|
||||
VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 verilator_profcfunc.1
|
||||
|
||||
VL_INST_INC_BLDDIR_FILES = \
|
||||
include/verilated.mk \
|
||||
@@ -297,7 +298,7 @@ installbin:
|
||||
# So important we use $< so VPATH is searched
|
||||
installman: $(VL_INST_MAN_FILES)
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(mandir)/man1
|
||||
for p in $< ; do \
|
||||
for p in $^ ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(mandir)/man1/$$p; \
|
||||
done
|
||||
|
||||
@@ -317,6 +318,8 @@ installdata:
|
||||
; for p in $(VL_INST_DATA_SRCDIR_FILES) ; do \
|
||||
$(INSTALL_DATA) $$p $(DESTDIR)$(pkgdatadir)/examples/$$p; \
|
||||
done
|
||||
$(SHELL) ${srcdir}/mkinstalldirs $(DESTDIR)$(pkgconfigdir)
|
||||
$(INSTALL_DATA) verilator.pc $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
# We don't trust rm -rf, so rmdir instead as it will fail if user put in other files
|
||||
uninstall:
|
||||
@@ -326,6 +329,7 @@ uninstall:
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_BLDDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir) && rm -f $(VL_INST_INC_SRCDIR_FILES)
|
||||
-cd $(DESTDIR)$(pkgdatadir)/examples && rm -f $(VL_INST_DATA_SRCDIR_FILES)
|
||||
-rm $(DESTDIR)$(pkgconfigdir)/verilator.pc
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/bin
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include/vltstd
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/include
|
||||
@@ -335,6 +339,7 @@ uninstall:
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples/test_v
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)/examples
|
||||
-rmdir $(DESTDIR)$(pkgdatadir)
|
||||
-rmdir $(DESTDIR)$(pkgconfigdir)
|
||||
|
||||
install: all_nomsg install-all
|
||||
install-all: installbin installman installdata install-msg
|
||||
@@ -420,7 +425,7 @@ ftp: info
|
||||
install-msg:
|
||||
@echo "Installed!"
|
||||
@echo
|
||||
@echo "Fod documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For documentation see 'man verilator' or 'verilator --help'"
|
||||
@echo "For forums and to report bugs see http://www.veripool.org/verilator"
|
||||
@echo
|
||||
|
||||
|
||||
+8
-1
@@ -1359,6 +1359,7 @@ And link with SystemC. Note your path to the libraries may vary,
|
||||
depending on the operating system.
|
||||
|
||||
export SYSTEMC_LIBDIR=/path/to/where/libsystemc.a/exists
|
||||
export LD_LIBRARY_PATH=$SYSTEMC_LIBDIR:$LD_LIBRARY_PATH
|
||||
# Might be needed if SystemC 2.3.0
|
||||
export SYSTEMC_CXX_FLAGS=-pthread
|
||||
|
||||
@@ -1498,6 +1499,12 @@ After running Make, the C++ compiler should produce the following:
|
||||
|
||||
=over 4
|
||||
|
||||
=item LD_LIBRARY_PATH
|
||||
|
||||
A generic Linux/OS variable specifying what directories have shared object
|
||||
(.so) files. This path should include SystemC and any other shared objects
|
||||
needed at runtime.
|
||||
|
||||
=item OBJCACHE
|
||||
|
||||
Optionally specifies a caching or distribution program to place in front of
|
||||
@@ -2887,7 +2894,7 @@ this warning is enabled only if user has explicitly marked some signal as
|
||||
clocker using command line option or in-source meta comment (see C<--clk>).
|
||||
|
||||
The warning can be disabled without affecting the simulation result. But it
|
||||
is recommanded to check the warning as this may degrade the performance of
|
||||
is recommended to check the warning as this may degrade the performance of
|
||||
the Verilated model.
|
||||
|
||||
=item CMPCONST
|
||||
|
||||
+4
-2
@@ -6,9 +6,9 @@
|
||||
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[3.872 2015-04-05])
|
||||
AC_INIT([Verilator],[3.874 2015-06-06])
|
||||
AC_CONFIG_HEADER(src/config_build.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h)
|
||||
AC_CONFIG_FILES(Makefile src/Makefile src/Makefile_obj include/verilated.mk include/verilated_config.h verilator.pc)
|
||||
|
||||
AC_MSG_RESULT([configuring for $PACKAGE_STRING])
|
||||
|
||||
@@ -161,6 +161,8 @@ AC_SUBST(CFG_CXXFLAGS_NO_UNUSED)
|
||||
# Other install directories
|
||||
pkgdatadir=${datadir}/verilator
|
||||
AC_SUBST(pkgdatadir)
|
||||
pkgconfigdir=${datadir}/pkgconfig
|
||||
AC_SUBST(pkgconfigdir)
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
+3
-3
@@ -594,13 +594,13 @@ static inline void VL_ASSIGNBIT_WO(int, int bit, WDataOutP owp, IData) {
|
||||
|
||||
#define VL_ASSIGN_SWI(obits,svar,rd) { \
|
||||
sc_bv<obits> _bvtemp; \
|
||||
_bvtemp.set_word(0,rd); \
|
||||
_bvtemp.set_word(0,(rd)); \
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
#define VL_ASSIGN_SWQ(obits,svar,rd) { \
|
||||
sc_bv<obits> _bvtemp; \
|
||||
_bvtemp.set_word(0,rd); \
|
||||
_bvtemp.set_word(1,rd>>VL_WORDSIZE); \
|
||||
_bvtemp.set_word(0,(IData)(rd)); \
|
||||
_bvtemp.set_word(1,(IData)((rd)>>VL_WORDSIZE)); \
|
||||
svar.write(_bvtemp); \
|
||||
}
|
||||
#define VL_ASSIGN_SWW(obits,svar,rwp) { \
|
||||
|
||||
@@ -421,7 +421,7 @@ public:
|
||||
do { \
|
||||
va_list args; \
|
||||
va_start(args, message); \
|
||||
vsnprintf(m_buff, sizeof(m_buff), message.c_str(), args); \
|
||||
VL_VSNPRINTF(m_buff, sizeof(m_buff), message.c_str(), args); \
|
||||
va_end(args); \
|
||||
} while (0)
|
||||
|
||||
|
||||
+17
-1
@@ -139,7 +139,7 @@ typedef unsigned char uint8_t; ///< 8-bit unsigned type (backward comp
|
||||
typedef unsigned short int uint16_t; ///< 16-bit unsigned type (backward compatibility)
|
||||
typedef unsigned char vluint8_t; ///< 8-bit unsigned type
|
||||
typedef unsigned short int vluint16_t; ///< 16-bit unsigned type
|
||||
# ifdef __uint32_t_defined // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
# if defined(__uint32_t_defined) || defined(___int32_t_defined) // Newer Cygwin uint32_t in stdint.h as an unsigned int
|
||||
typedef int32_t vlsint32_t; ///< 32-bit signed type
|
||||
typedef uint32_t vluint32_t; ///< 32-bit unsigned type
|
||||
# else // Older Cygwin has long==uint32_t
|
||||
@@ -207,6 +207,22 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# define VL_VSNPRINTF vl_vsnprintf
|
||||
inline int vl_vsnprintf(char* str, size_t size, const char* format, va_list ap) {
|
||||
int count = -1;
|
||||
if (size != 0) {
|
||||
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
|
||||
}
|
||||
if (count == -1) {
|
||||
count = _vscprintf(format, ap);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#else
|
||||
# define VL_VSNPRINTF vsnprintf
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
// File system functions
|
||||
|
||||
|
||||
@@ -1079,6 +1079,7 @@ public:
|
||||
//TODO stomp these width functions out, and call via dtypep() instead
|
||||
int width() const;
|
||||
int widthMin() const;
|
||||
int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); }
|
||||
int widthWords() const { return VL_WORDS_I(width()); }
|
||||
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
||||
bool isWide() const { return (width()>VL_QUADSIZE); }
|
||||
|
||||
+4
-3
@@ -103,7 +103,7 @@ public:
|
||||
return num().isCaseEq(samep->castConst()->num()); }
|
||||
virtual int instrCount() const { return widthInstrs(); }
|
||||
bool isEqAllOnes() const { return num().isEqAllOnes(width()); }
|
||||
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMin()); }
|
||||
bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); }
|
||||
};
|
||||
|
||||
class AstRange : public AstNode {
|
||||
@@ -3310,7 +3310,8 @@ public:
|
||||
dtypeSetLogicSized(width,width,AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(ExtendS, EXTENDS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) {
|
||||
out.opExtendS(lhs, lhsp()->widthMin()); }
|
||||
out.opExtendS(lhs, lhsp()->widthMinV());
|
||||
}
|
||||
virtual string emitVerilog() { return "%l"; }
|
||||
virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; }
|
||||
virtual bool cleanOut() {return false;} virtual bool cleanLhs() {return true;}
|
||||
@@ -4150,7 +4151,7 @@ public:
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(ShiftRS, SHIFTRS)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMin()); }
|
||||
out.opShiftRS(lhs,rhs,lhsp()->widthMinV()); }
|
||||
virtual string emitVerilog() { return "%k(%l %f>>> %r)"; }
|
||||
virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
|
||||
+8
-11
@@ -204,6 +204,12 @@ public:
|
||||
|
||||
class BrokenCheckVisitor : public AstNVisitor {
|
||||
private:
|
||||
void checkWidthMin(AstNode* nodep) {
|
||||
if (nodep->width() != nodep->widthMin()
|
||||
&& v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH) {
|
||||
nodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
BrokenTable::setUnder(nodep,true);
|
||||
if (const char* whyp=nodep->broken()) {
|
||||
@@ -220,18 +226,9 @@ private:
|
||||
if (nodep->dtypep()) nodep->v3fatalSrc("DType on node without hasDType(): "<<nodep->prettyTypeName());
|
||||
}
|
||||
if (nodep->getChildDTypep()) nodep->v3fatalSrc("childDTypep() non-null on node after should have removed");
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) {
|
||||
if (dnodep->width() != dnodep->widthMin()
|
||||
&& v3Global.assertWidthsMatch()) {
|
||||
dnodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (v3Global.assertWidthsMatch()) {
|
||||
if (nodep->width() != nodep->widthMin()) {
|
||||
nodep->v3fatalSrc("Width != WidthMin");
|
||||
}
|
||||
if (AstNodeDType* dnodep = nodep->castNodeDType()) checkWidthMin(dnodep);
|
||||
}
|
||||
checkWidthMin(nodep);
|
||||
nodep->iterateChildrenConst(*this);
|
||||
BrokenTable::setUnder(nodep,false);
|
||||
}
|
||||
|
||||
@@ -345,6 +345,7 @@ private:
|
||||
while (!m_readEof && (size<0 || size>sizegot)) {
|
||||
ssize_t todo = INFILTER_IPC_BUFSIZ;
|
||||
if (size>0 && size<todo) todo = size;
|
||||
errno = 0;
|
||||
ssize_t got = read (fd, buf, todo);
|
||||
//UINFO(9,"RD GOT g "<< got<<" e "<<errno<<" "<<strerror(errno)<<endl); usleep(50*1000);
|
||||
if (got>0) {
|
||||
@@ -384,6 +385,7 @@ private:
|
||||
if (!m_pid) { v3error("--pipe-filter: write to closed file\n"); m_readEof = true; stop(); }
|
||||
unsigned offset = 0;
|
||||
while (!m_readEof && out.length()>offset) {
|
||||
errno = 0;
|
||||
int got = write (m_writeFd, (out.c_str())+offset, out.length()-offset);
|
||||
//UINFO(9,"WR GOT g "<< got<<" e "<<errno<<" "<<strerror(errno)<<endl); usleep(50*1000);
|
||||
if (got>0) offset += got;
|
||||
|
||||
+2
-2
@@ -362,6 +362,7 @@ private:
|
||||
nodep->iterateChildren(*this);
|
||||
//if (debug()>6) m_graph.dump();
|
||||
if (debug()>6) m_graph.dumpDotFilePrefixed("gate_pre");
|
||||
warnSignals(); // Before loss of sync/async pointers
|
||||
m_graph.removeRedundantEdgesSum(&V3GraphEdge::followAlwaysTrue);
|
||||
m_graph.dumpDotFilePrefixed("gate_simp");
|
||||
// Find gate interconnect and optimize
|
||||
@@ -373,8 +374,7 @@ private:
|
||||
// Remove redundant logic
|
||||
if (v3Global.opt.oDedupe()) dedupe();
|
||||
if (v3Global.opt.oAssemble()) mergeAssigns();
|
||||
// Warn
|
||||
warnSignals();
|
||||
// Consumption warnings
|
||||
consumedMark();
|
||||
m_graph.dumpDotFilePrefixed("gate_opt");
|
||||
// Rewrite assignments
|
||||
|
||||
+25
-5
@@ -36,15 +36,35 @@ class AstNetlist;
|
||||
|
||||
|
||||
//######################################################################
|
||||
// V3 - The top level class for the entire program
|
||||
|
||||
class VWidthMinUsage {
|
||||
public:
|
||||
enum en {
|
||||
LINT_WIDTH,
|
||||
MATCHES_WIDTH,
|
||||
VERILOG_WIDTH
|
||||
};
|
||||
enum en m_e;
|
||||
inline VWidthMinUsage () : m_e(LINT_WIDTH) {}
|
||||
inline VWidthMinUsage (en _e) : m_e(_e) {}
|
||||
explicit inline VWidthMinUsage (int _e) : m_e(static_cast<en>(_e)) {}
|
||||
operator en () const { return m_e; }
|
||||
};
|
||||
inline bool operator== (VWidthMinUsage lhs, VWidthMinUsage rhs) { return (lhs.m_e == rhs.m_e); }
|
||||
inline bool operator== (VWidthMinUsage lhs, VWidthMinUsage::en rhs) { return (lhs.m_e == rhs); }
|
||||
inline bool operator== (VWidthMinUsage::en lhs, VWidthMinUsage rhs) { return (lhs == rhs.m_e); }
|
||||
|
||||
//######################################################################
|
||||
// V3Global - The top level class for the entire program
|
||||
|
||||
class V3Global {
|
||||
// Globals
|
||||
AstNetlist* m_rootp; // Root of entire netlist
|
||||
VWidthMinUsage m_widthMinUsage; // What AstNode::widthMin() is used for
|
||||
|
||||
int m_debugFileNumber; // Number to append to debug files created
|
||||
int m_assertWidthsMatch; // Tree should have width()==widthMin()
|
||||
bool m_assertDTypesResolved; // Tree should have dtypep()'s
|
||||
bool m_assertWidthsMatch; // Tree should have width()==widthMin()
|
||||
bool m_constRemoveXs; // Const needs to strip any Xs
|
||||
bool m_needHInlines; // Need __Inlines file
|
||||
bool m_needHeavy; // Need verilated_heavy.h include
|
||||
@@ -58,8 +78,8 @@ public:
|
||||
// CREATORS
|
||||
V3Global() {
|
||||
m_debugFileNumber = 0;
|
||||
m_widthMinUsage = VWidthMinUsage::LINT_WIDTH;
|
||||
m_assertDTypesResolved = false;
|
||||
m_assertWidthsMatch = false;
|
||||
m_constRemoveXs = false;
|
||||
m_needHInlines = false;
|
||||
m_needHeavy = false;
|
||||
@@ -71,15 +91,15 @@ public:
|
||||
void clear();
|
||||
// ACCESSORS (general)
|
||||
AstNetlist* rootp() const { return m_rootp; }
|
||||
VWidthMinUsage widthMinUsage() const { return m_widthMinUsage; }
|
||||
bool assertDTypesResolved() const { return m_assertDTypesResolved; }
|
||||
bool assertWidthsMatch() const { return m_assertWidthsMatch; }
|
||||
|
||||
// METHODS
|
||||
void readFiles();
|
||||
void checkTree();
|
||||
static void dumpCheckGlobalTree(const string& filename, int newNumber=0, bool doDump=true);
|
||||
void assertDTypesResolved(bool flag) { m_assertDTypesResolved = flag; }
|
||||
void assertWidthsMatch(bool flag) { m_assertWidthsMatch = flag; }
|
||||
void widthMinUsage(const VWidthMinUsage& flag) { m_widthMinUsage = flag; }
|
||||
bool constRemoveXs() const { return m_constRemoveXs; }
|
||||
void constRemoveXs(bool flag) { m_constRemoveXs = flag; }
|
||||
string debugFilename(const string& nameComment, int newNumber=0) {
|
||||
|
||||
+97
-71
@@ -239,81 +239,107 @@ public:
|
||||
virtual ~InstDeVisitor() {}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Inst static function
|
||||
|
||||
class InstStatic {
|
||||
private:
|
||||
static int debug() {
|
||||
static int level = -1;
|
||||
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel(__FILE__);
|
||||
return level;
|
||||
}
|
||||
InstStatic() {} // Static class
|
||||
|
||||
static AstNode* extendOrSel(FileLine* fl, AstNode* rhsp, AstNode* cmpWidthp) {
|
||||
if (cmpWidthp->width() > rhsp->width()) {
|
||||
rhsp = (rhsp->isSigned()
|
||||
? (new AstExtendS(fl, rhsp))->castNode()
|
||||
: (new AstExtend (fl, rhsp))->castNode());
|
||||
rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above
|
||||
} else if (cmpWidthp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (fl, rhsp, 0, cmpWidthp->width());
|
||||
rhsp->dtypeFrom(cmpWidthp); // Need proper widthMin, which may differ from AstSel created above
|
||||
}
|
||||
// else don't change dtype, as might be e.g. array of something
|
||||
return rhsp;
|
||||
}
|
||||
|
||||
public:
|
||||
static AstAssignW* pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
|
||||
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
|
||||
AstBasicDType* connBasicp = NULL;
|
||||
AstAssignW* assignp = NULL;
|
||||
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
|
||||
//
|
||||
if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
|
||||
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
|
||||
// Done. Same data type
|
||||
} else if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->isIfaceRef()) {
|
||||
// Done. Interface
|
||||
} else if (!alwaysCvt
|
||||
&& connBasicp
|
||||
&& pinBasicp
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = ((string)(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
|
||||
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
|
||||
+"__"+cellp->name()+"__"+pinp->name());
|
||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
UINFO(5,"pinRecon width "<<pinVarp->width()<<" >? "<<rhsp->width()<<" >? "<<pinexprp->width()<<endl);
|
||||
rhsp = extendOrSel (pinp->fileline(), rhsp, pinVarp);
|
||||
pinp->exprp(new AstVarRef (newvarp->fileline(), newvarp, true));
|
||||
AstNode* rhsSelp = extendOrSel (pinp->fileline(), rhsp, pinexprp);
|
||||
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsSelp);
|
||||
} else {
|
||||
// V3 width should have range/extended to make the widths correct
|
||||
assignp = new AstAssignW (pinp->fileline(),
|
||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||
pinexprp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||
}
|
||||
if (assignp) cellp->addNextHere(assignp);
|
||||
//if (debug()) { pinp->dumpTree(cout,"- out:"); }
|
||||
//if (debug()) { assignp->dumpTree(cout,"- aout:"); }
|
||||
}
|
||||
return assignp;
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Inst class functions
|
||||
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule*,
|
||||
AstAssignW* V3Inst::pinReconnectSimple(AstPin* pinp, AstCell* cellp, AstNodeModule* modp,
|
||||
bool forTristate, bool alwaysCvt) {
|
||||
// If a pin connection is "simple" leave it as-is
|
||||
// Else create a intermediate wire to perform the interconnect
|
||||
// Return the new assignment, if one was made
|
||||
// Note this module calles cloneTree() via new AstVar
|
||||
AstVar* pinVarp = pinp->modVarp();
|
||||
AstVarRef* connectRefp = pinp->exprp()->castVarRef();
|
||||
AstBasicDType* pinBasicp = pinVarp->dtypep()->basicp(); // Maybe NULL
|
||||
AstBasicDType* connBasicp = NULL;
|
||||
AstAssignW* assignp = NULL;
|
||||
if (connectRefp) connBasicp = connectRefp->varp()->dtypep()->basicp();
|
||||
//
|
||||
if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep())
|
||||
&& !connectRefp->varp()->isSc()) { // Need the signal as a 'shell' to convert types
|
||||
// Done. Same data type
|
||||
} else if (!alwaysCvt
|
||||
&& connectRefp
|
||||
&& connectRefp->varp()->isIfaceRef()) {
|
||||
// Done. Interface
|
||||
} else if (!alwaysCvt
|
||||
&& connBasicp
|
||||
&& pinBasicp
|
||||
&& connBasicp->width() == pinBasicp->width()
|
||||
&& connBasicp->lsb() == pinBasicp->lsb()
|
||||
&& !connectRefp->varp()->isSc() // Need the signal as a 'shell' to convert types
|
||||
&& connBasicp->width() == pinVarp->width()
|
||||
&& 1) {
|
||||
// Done. One to one interconnect won't need a temporary variable.
|
||||
} else if (!alwaysCvt && !forTristate && pinp->exprp()->castConst()) {
|
||||
// Done. Constant.
|
||||
} else {
|
||||
// Make a new temp wire
|
||||
//if (1||debug()>=9) { pinp->dumpTree(cout,"-in_pin:"); }
|
||||
AstNode* pinexprp = pinp->exprp()->unlinkFrBack();
|
||||
string newvarname = ((string)(pinVarp->isOutput() ? "__Vcellout" : "__Vcellinp")
|
||||
+(forTristate?"t":"") // Prevent name conflict if both tri & non-tri add signals
|
||||
+"__"+cellp->name()+"__"+pinp->name());
|
||||
AstVar* newvarp = new AstVar (pinVarp->fileline(), AstVarType::MODULETEMP, newvarname, pinVarp);
|
||||
// Important to add statement next to cell, in case there is a generate with same named cell
|
||||
cellp->addNextHere(newvarp);
|
||||
if (pinVarp->isInout()) {
|
||||
pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be direct one-to-one connection (without any expression)");
|
||||
} else if (pinVarp->isOutput()) {
|
||||
// See also V3Inst
|
||||
AstNode* rhsp = new AstVarRef(pinp->fileline(), newvarp, false);
|
||||
if (pinVarp->width() > rhsp->width()) {
|
||||
if (rhsp->isSigned()) {
|
||||
rhsp = new AstExtendS(pinp->fileline(), rhsp);
|
||||
} else {
|
||||
rhsp = new AstExtend (pinp->fileline(), rhsp);
|
||||
}
|
||||
} else if (pinVarp->width() < rhsp->width()) {
|
||||
rhsp = new AstSel (pinp->fileline(), rhsp, 0, pinVarp->width());
|
||||
}
|
||||
rhsp->dtypeFrom(pinVarp); // Need proper widthMin, which may differ from AstSel created above
|
||||
assignp = new AstAssignW (pinp->fileline(), pinexprp, rhsp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, true));
|
||||
} else {
|
||||
// V3 width should have range/extended to make the widths correct
|
||||
assignp = new AstAssignW (pinp->fileline(),
|
||||
new AstVarRef(pinp->fileline(), newvarp, true),
|
||||
pinexprp);
|
||||
pinp->exprp(new AstVarRef (pinexprp->fileline(), newvarp, false));
|
||||
}
|
||||
if (assignp) cellp->addNextHere(assignp);
|
||||
//if (debug()) { pinp->dumpTree(cout,"- out:"); }
|
||||
//if (debug()) { assignp->dumpTree(cout,"- aout:"); }
|
||||
}
|
||||
return assignp;
|
||||
return InstStatic::pinReconnectSimple(pinp, cellp, modp, forTristate, alwaysCvt);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
||||
@@ -1569,6 +1569,24 @@ V3Number& V3Number::opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, const V3Number& lsb, int width) {
|
||||
return opSelInto(lhs, lsb.toSInt(), width);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opSelInto (const V3Number& lhs, int lsbval, int width) {
|
||||
// this[lsbval+width-1 : lsbval] = lhs; Other bits of this are not affected
|
||||
int ibit=0;
|
||||
for(int bit=lsbval; bit<lsbval+width; bit++) {
|
||||
if (ibit>=0 && ibit<lhs.width()) {
|
||||
setBit(bit,lhs.bitIs(ibit));
|
||||
} else {
|
||||
setBit(bit,'x');
|
||||
}
|
||||
ibit++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
|
||||
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
|
||||
if (lhstrue.bitIs0(0)) {
|
||||
|
||||
@@ -235,6 +235,8 @@ public:
|
||||
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opSel (const V3Number& lhs, uint32_t rhs, uint32_t ths);
|
||||
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
|
||||
V3Number& opSelInto (const V3Number& lhs, int lsb, int width);
|
||||
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
|
||||
+20
-9
@@ -58,6 +58,7 @@ static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t,l);
|
||||
%x DEFFORM
|
||||
%x DEFVAL
|
||||
%x DEFCMT
|
||||
%x STRIFY
|
||||
%x ARGMODE
|
||||
%x INCMODE
|
||||
%x PRTMODE
|
||||
@@ -80,8 +81,8 @@ drop [\032]
|
||||
/**************************************************************/
|
||||
%%
|
||||
|
||||
<INITIAL>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
<INITIAL,STRIFY>^{ws}*"`line"{ws}+.*{crnl} { LEXP->lineDirective(yytext);
|
||||
return(VP_LINE); }
|
||||
|
||||
/* Special directives we recognize */
|
||||
<INITIAL>"`define" { return(VP_DEFINE); }
|
||||
@@ -93,17 +94,15 @@ drop [\032]
|
||||
<INITIAL>"`include" { return(VP_INCLUDE); }
|
||||
<INITIAL>"`undef" { return(VP_UNDEF); }
|
||||
<INITIAL>"`undefineall" { return(VP_UNDEFINEALL); }
|
||||
|
||||
/* Optional directives we recognize */
|
||||
<INITIAL>"`__FILE__" { static string rtnfile;
|
||||
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
||||
<INITIAL,STRIFY>"`__FILE__" { static string rtnfile;
|
||||
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename();
|
||||
rtnfile += '"'; yytext=(char*)rtnfile.c_str(); yyleng = rtnfile.length();
|
||||
return (VP_STRING); }
|
||||
<INITIAL>"`__LINE__" { static char buf[10];
|
||||
<INITIAL,STRIFY>"`__LINE__" { static char buf[10];
|
||||
sprintf(buf, "%d",LEXP->curFilelinep()->lineno());
|
||||
yytext = buf; yyleng = strlen(yytext);
|
||||
return (VP_TEXT); }
|
||||
<INITIAL>"`error" { if (!pedantic()) return (VP_ERROR); else return(VP_DEFREF); }
|
||||
|
||||
/* Pass-through strings */
|
||||
<INITIAL>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
@@ -118,8 +117,20 @@ drop [\032]
|
||||
else return (VP_STRING); }
|
||||
|
||||
/* Stringification */
|
||||
<INITIAL>{tickquote} { return VP_STRIFY; }
|
||||
<INITIAL>"`\\`\"" { return VP_BACKQUOTE; }
|
||||
<INITIAL>{tickquote} { yy_push_state(STRIFY); return VP_STRIFY; }
|
||||
<STRIFY><<EOF>> { linenoInc(); yyerrorf("EOF in unterminated '\""); yyleng=0; yyterminate(); }
|
||||
<STRIFY>"`\\`\"" { return VP_BACKQUOTE; }
|
||||
<STRIFY>{quote} { yy_push_state(STRMODE); yymore(); }
|
||||
<STRIFY>{tickquote} { yy_pop_state(); return VP_STRIFY; }
|
||||
<STRIFY>{symbdef} { return (VP_SYMBOL); }
|
||||
<STRIFY>{symbdef}`` { yyleng-=2; return (VP_SYMBOL_JOIN); }
|
||||
<STRIFY>"`"{symbdef} { return (VP_DEFREF); }
|
||||
<STRIFY>"`"{symbdef}`` { yyleng-=2; return (VP_DEFREF_JOIN); }
|
||||
<STRIFY>{crnl} { linenoInc(); yytext=(char*)"\n"; yyleng=1; return(VP_WHITE); }
|
||||
<STRIFY>{wsn}+ { return (VP_WHITE); }
|
||||
<STRIFY>{drop} { }
|
||||
<STRIFY>[\r] { }
|
||||
<STRIFY>. { return (VP_TEXT); }
|
||||
|
||||
/* Protected blocks */
|
||||
<INITIAL>"`protected" { yy_push_state(PRTMODE); yymore(); }
|
||||
|
||||
+48
-11
@@ -224,16 +224,24 @@ private:
|
||||
if (!vscp) nodep->v3fatalSrc("Not linked");
|
||||
return vscp;
|
||||
}
|
||||
|
||||
int unrollCount() {
|
||||
return m_params ? v3Global.opt.unrollCount()*16
|
||||
: v3Global.opt.unrollCount();
|
||||
}
|
||||
|
||||
bool jumpingOver(AstNode* nodep) {
|
||||
// True to jump over this node - all visitors must call this up front
|
||||
return (m_jumpp && m_jumpp->labelp()!=nodep);
|
||||
}
|
||||
void assignOutNumber(AstNodeAssign* nodep, AstNode* vscp, const V3Number* nump) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
if (nodep->castAssignDly()) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
newOutNumber(vscp)->opAssign(*nump);
|
||||
} else {
|
||||
newNumber(vscp)->opAssign(*nump);
|
||||
newOutNumber(vscp)->opAssign(*nump);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||
@@ -438,7 +446,43 @@ private:
|
||||
if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns");
|
||||
m_anyAssignComb = true;
|
||||
}
|
||||
if (!nodep->lhsp()->castVarRef()) {
|
||||
if (AstSel* selp = nodep->lhsp()->castSel()) {
|
||||
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
|
||||
checkNodeInfo(selp);
|
||||
AstVarRef* varrefp = selp->fromp()->castVarRef();
|
||||
if (!varrefp) {
|
||||
clearOptimizable(nodep, "Select LHS isn't simple variable");
|
||||
return;
|
||||
}
|
||||
if (m_checkOnly) {
|
||||
nodep->iterateChildren(*this);
|
||||
} else {
|
||||
selp->lsbp()->iterateAndNext(*this);
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
if (optimizable()) {
|
||||
AstNode* vscp = varOrScope(varrefp);
|
||||
if (optimizable()) {
|
||||
V3Number outnum (nodep->fileline(), varrefp->varp()->widthMin());
|
||||
if (V3Number* outnump = fetchOutNumberNull(vscp)) {
|
||||
outnum = *outnump;
|
||||
} else if (V3Number* outnump = fetchNumberNull(vscp)) {
|
||||
outnum = *outnump;
|
||||
} else { // Assignment to unassigned variable, all bits are X or 0
|
||||
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
|
||||
outnum.setAllBits0();
|
||||
} else {
|
||||
outnum.setAllBitsX();
|
||||
}
|
||||
}
|
||||
outnum.opSelInto(*fetchNumber(nodep->rhsp()),
|
||||
*fetchNumber(selp->lsbp()),
|
||||
selp->widthConst());
|
||||
assignOutNumber(nodep, vscp, &outnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!nodep->lhsp()->castVarRef()) {
|
||||
clearOptimizable(nodep, "LHS isn't simple variable");
|
||||
}
|
||||
else if (m_checkOnly) {
|
||||
@@ -448,14 +492,7 @@ private:
|
||||
nodep->rhsp()->iterateAndNext(*this);
|
||||
if (optimizable()) {
|
||||
AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef());
|
||||
// Copy by value, not reference, as we don't want a=a+1 to get right results
|
||||
if (nodep->castAssignDly()) {
|
||||
// Don't do setNumber, as value isn't yet visible to following statements
|
||||
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
} else {
|
||||
newNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
|
||||
}
|
||||
assignOutNumber(nodep, vscp, fetchNumber(nodep->rhsp()));
|
||||
}
|
||||
}
|
||||
m_inDlyAssign = false;
|
||||
|
||||
+31
-10
@@ -1009,8 +1009,10 @@ private:
|
||||
//if (debug()) newp->dumpTree(cout," CastOut: ");
|
||||
}
|
||||
virtual void visit(AstCastSize* nodep, AstNUser* vup) {
|
||||
// IEEE: Signedness of result is same as self-determined signedness
|
||||
// However, the result is same as BITSEL, so we do not sign extend the LHS
|
||||
if (!nodep->rhsp()->castConst()) nodep->v3fatalSrc("Unsupported: Non-const cast of size");
|
||||
//if (debug()) nodep->dumpTree(cout," CastPre: ");
|
||||
//if (debug()) nodep->dumpTree(cout," CastSizePre: ");
|
||||
if (vup->c()->prelim()) {
|
||||
int width = nodep->rhsp()->castConst()->toSInt();
|
||||
if (width < 1) { nodep->v3error("Size-changing cast to zero or negative size"); width=1; }
|
||||
@@ -1020,12 +1022,29 @@ private:
|
||||
nodep->v3error("Unsupported: Size-changing cast on non-basic data type");
|
||||
underDtp = nodep->findLogicBoolDType()->castBasicDType();
|
||||
}
|
||||
AstNodeDType* newDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(width, width, underDtp->numeric())
|
||||
: nodep->findBitDType(width, width, underDtp->numeric()));
|
||||
nodep->dtypep(newDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
iterateCheck(nodep,"Cast LHS",nodep->lhsp(),CONTEXT,FINAL,newDtp,EXTEND_EXP,false);
|
||||
// A cast propagates its size to the lower expression and is included in the maximum
|
||||
// width, so 23'(1'b1 + 1'b1) uses 23-bit math, but 1'(2'h2 * 2'h1) uses two-bit math.
|
||||
// However the output width is exactly that requested.
|
||||
// So two steps, first do the calculation's width (max of the two widths)
|
||||
{
|
||||
int calcWidth = max(width, underDtp->width());
|
||||
AstNodeDType* calcDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric())
|
||||
: nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric()));
|
||||
nodep->dtypep(calcDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
iterateCheck(nodep,"Cast expr",nodep->lhsp(),CONTEXT,FINAL,calcDtp,EXTEND_EXP,false);
|
||||
}
|
||||
if (debug()) nodep->dumpTree(cout," CastSizeClc: ");
|
||||
// Next step, make the proper output width
|
||||
{
|
||||
AstNodeDType* outDtp = (underDtp->keyword().isFourstate()
|
||||
? nodep->findLogicDType(width, width, underDtp->numeric())
|
||||
: nodep->findBitDType(width, width, underDtp->numeric()));
|
||||
nodep->dtypep(outDtp);
|
||||
// We ignore warnings as that is sort of the point of a cast
|
||||
widthCheckSized(nodep,"Cast expr",nodep->lhsp(),outDtp,EXTEND_EXP,false);
|
||||
}
|
||||
}
|
||||
if (vup->c()->final()) {
|
||||
// CastSize not needed once sizes determined
|
||||
@@ -1033,6 +1052,7 @@ private:
|
||||
nodep->replaceWith(underp);
|
||||
pushDeletep(nodep); nodep=NULL;
|
||||
}
|
||||
//if (debug()) nodep->dumpTree(cout," CastSizeOut: ");
|
||||
}
|
||||
virtual void visit(AstVar* nodep, AstNUser* vup) {
|
||||
//if (debug()) nodep->dumpTree(cout," InitPre: ");
|
||||
@@ -3005,9 +3025,10 @@ private:
|
||||
// which bits to truncate.
|
||||
AstNodeAssign* assignp = nodep->castNodeAssign();
|
||||
AstPin* pinp = nodep->castPin();
|
||||
if (assignp && assignp->lhsp()->castNodeStream()) { }
|
||||
else if (pinp && !pinp->modVarp()->isInput()) { }
|
||||
else {
|
||||
if (assignp && assignp->lhsp()->castNodeStream()) {
|
||||
} else if (pinp && !pinp->modVarp()->isInput()) { // V3Inst::pinReconnectSimple must deal
|
||||
UINFO(5,"pinInSizeMismatch: "<<pinp);
|
||||
} else {
|
||||
fixWidthExtend(underp, expDTypep, extendRule); underp=NULL;//Changed
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -187,7 +187,7 @@ void process () {
|
||||
// Commit to the widths we've chosen; Make widthMin==width
|
||||
V3Width::widthCommit(v3Global.rootp());
|
||||
v3Global.assertDTypesResolved(true);
|
||||
v3Global.assertWidthsMatch(true);
|
||||
v3Global.widthMinUsage(VWidthMinUsage::MATCHES_WIDTH);
|
||||
|
||||
// Coverage insertion
|
||||
// Before we do dead code elimination and inlining, or we'll lose it.
|
||||
@@ -448,7 +448,7 @@ void process () {
|
||||
|
||||
// Here down, widthMin() is the Verilog width, and width() is the C++ width
|
||||
// Bits between widthMin() and width() are irrelevant, but may be non zero.
|
||||
v3Global.assertWidthsMatch(false);
|
||||
v3Global.widthMinUsage(VWidthMinUsage::VERILOG_WIDTH);
|
||||
|
||||
// Make all math operations either 8, 16, 32 or 64 bits
|
||||
V3Clean::cleanAll(v3Global.rootp());
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ void yyerrorf(const char* format, ...) {
|
||||
|
||||
va_list ap;
|
||||
va_start(ap,format);
|
||||
vsnprintf(msg,maxlen,format,ap);
|
||||
VL_VSNPRINTF(msg,maxlen,format,ap);
|
||||
msg[maxlen-1] = '\0';
|
||||
va_end(ap);
|
||||
|
||||
|
||||
@@ -13,6 +13,23 @@ module t;
|
||||
logic [15:0] allones = 16'hffff;
|
||||
parameter FOUR = 4;
|
||||
|
||||
// bug925
|
||||
localparam [6:0] RESULT = 7'((6*9+92)%96);
|
||||
|
||||
logic signed [14:0] samp0 = 15'h0000;
|
||||
logic signed [14:0] samp1 = 15'h0000;
|
||||
logic signed [14:0] samp2 = 15'h6000;
|
||||
logic signed [11:0] coeff0 = 12'h009;
|
||||
logic signed [11:0] coeff1 = 12'h280;
|
||||
logic signed [11:0] coeff2 = 12'h4C5;
|
||||
logic signed [26:0] mida = ((27'(coeff2 * samp2) >>> 11));
|
||||
// verilator lint_off WIDTH
|
||||
logic signed [26:0] midb = 15'((27'(coeff2 * samp2) >>> 11));
|
||||
// verilator lint_on WIDTH
|
||||
logic signed [14:0] outa = 15'((27'(coeff0 * samp0) >>> 11) + // 27' size casting in order for intermediate result to not be truncated to the width of LHS vector
|
||||
(27'(coeff1 * samp1) >>> 11) +
|
||||
(27'(coeff2 * samp2) >>> 11)); // 15' size casting to avoid synthesis/simulator warnings
|
||||
|
||||
initial begin
|
||||
if (4'shf > 4'sh0) $stop;
|
||||
if (signed'(4'hf) > 4'sh0) $stop;
|
||||
@@ -24,10 +41,15 @@ module t;
|
||||
if ((4+2)'(allones) !== 6'h3f) $stop;
|
||||
if ((4-2)'(allones) !== 2'h3) $stop;
|
||||
if ((FOUR+2)'(allones) !== 6'h3f) $stop;
|
||||
if (50 !== RESULT) $stop;
|
||||
|
||||
o = tocast_t'(4'b1);
|
||||
if (o != 4'b1) $stop;
|
||||
|
||||
if (15'h6cec != outa) $stop;
|
||||
if (27'h7ffecec != mida) $stop;
|
||||
if (27'h7ffecec != midb) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
@@ -18,6 +18,7 @@ if (!-r "$root/.git") {
|
||||
uint();
|
||||
printfll();
|
||||
cstr();
|
||||
vsnprintf();
|
||||
}
|
||||
|
||||
ok(1);
|
||||
@@ -86,4 +87,22 @@ sub cstr {
|
||||
}
|
||||
}
|
||||
|
||||
sub vsnprintf {
|
||||
my $files = "src/*.c* src/*.h include/*.c* include/*.h test_c/*.c* test_regress/t/*.c* test_regress/t/*.h";
|
||||
my $cmd = "cd $root && grep -n -P 'vsnprintf' $files | sort";
|
||||
print "C $cmd\n";
|
||||
my $grep = `$cmd`;
|
||||
my %names;
|
||||
foreach my $line (split /\n/, $grep) {
|
||||
if ($line =~ /\b(vsnprintf)\b/) {
|
||||
next if $line =~ /# *define\s*VL_VSNPRINTF/;
|
||||
print "$line\n";
|
||||
$names{$1} = 1;
|
||||
}
|
||||
}
|
||||
if (keys %names) {
|
||||
$Self->error("Files with vsnprintf, use VL_VSNPRINTF: ",join(' ',sort keys %names));
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/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,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,50 @@
|
||||
// DESCRIPTION:tor:ilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Wilson Snyder.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
wire [31:0] o;
|
||||
wire [31:0] oe;
|
||||
|
||||
Test test (/*AUTOINST*/
|
||||
// Outputs
|
||||
.o (o[31:0]),
|
||||
.oe (oe[31:0]));
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
if (o !== 32'h00000001) $stop;
|
||||
if (oe !== 32'h00000001) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module subimp(o,oe);
|
||||
output [31:0] o;
|
||||
assign o = 32'h12345679;
|
||||
output [31:0] oe;
|
||||
assign oe = 32'hab345679;
|
||||
endmodule
|
||||
|
||||
module Test(o,oe);
|
||||
output [31:0] o;
|
||||
output [31:0] oe;
|
||||
wire [31:0] xe;
|
||||
assign xe[31:1] = 0;
|
||||
// verilator lint_off IMPLICIT
|
||||
// verilator lint_off WIDTH
|
||||
subimp subimp(x, // x is implicit and one bit
|
||||
xe[0]); // xe explicit one bit
|
||||
assign o = x;
|
||||
assign oe = xe;
|
||||
// verilator lint_on WIDTH
|
||||
// verilator lint_on IMPLICIT
|
||||
endmodule
|
||||
@@ -29,12 +29,8 @@ module t (/*AUTOARG*/
|
||||
`endif
|
||||
if (sgn_wide[2:0] != 3'sh7) $stop;
|
||||
if (unsgn_wide[2:0] != 3'h7) $stop;
|
||||
if (sgn_wide !== 8'sh7) $stop;
|
||||
// Simulators differ here.
|
||||
if (sgn_wide !== 8'sbzzzzz111 // z-extension - NC
|
||||
`ifdef VERILATOR
|
||||
&& sgn_wide !== 8'sb00000111 // 0-extension - verilator as it doesn't have Z
|
||||
`endif
|
||||
&& sgn_wide !== 8'sb11111111) $stop; // sign extension - VCS
|
||||
if (unsgn_wide !== 8'sbzzzzz111
|
||||
&& unsgn_wide!== 8'sb00000111) $stop;
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/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,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,132 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This test demonstrates an issue with sign extension.
|
||||
// Assigning to localparms larger than 32 bits broke in 3.862
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Mike Thyer.
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
|
||||
localparam [ 0:0] one1_lp = 1;
|
||||
localparam [ 1:0] one2_lp = 1;
|
||||
localparam [ 2:0] one3_lp = 1;
|
||||
localparam [ 3:0] one4_lp = 1;
|
||||
localparam [ 4:0] one5_lp = 1;
|
||||
localparam [ 5:0] one6_lp = 1;
|
||||
localparam [ 6:0] one7_lp = 1;
|
||||
localparam [ 7:0] one8_lp = 1;
|
||||
localparam [ 8:0] one9_lp = 1;
|
||||
localparam [ 9:0] one10_lp = 1;
|
||||
localparam [19:0] one20_lp = 1;
|
||||
localparam [29:0] one30_lp = 1;
|
||||
localparam [30:0] one31_lp = 1;
|
||||
localparam [31:0] one32_lp = 1;
|
||||
localparam [32:0] one33_lp = 1;
|
||||
localparam [33:0] one34_lp = 1;
|
||||
localparam [34:0] one35_lp = 1;
|
||||
localparam [35:0] one36_lp = 1;
|
||||
localparam [36:0] one37_lp = 1;
|
||||
localparam [37:0] one38_lp = 1;
|
||||
localparam [38:0] one39_lp = 1;
|
||||
localparam [39:0] one40_lp = 1;
|
||||
localparam [49:0] one50_lp = 1;
|
||||
localparam [59:0] one60_lp = 1;
|
||||
localparam [60:0] one61_lp = 1;
|
||||
localparam [61:0] one62_lp = 1;
|
||||
localparam [62:0] one63_lp = 1;
|
||||
localparam [63:0] one64_lp = 1;
|
||||
localparam [64:0] one65_lp = 1;
|
||||
localparam [65:0] one66_lp = 1;
|
||||
localparam [66:0] one67_lp = 1;
|
||||
localparam [67:0] one68_lp = 1;
|
||||
localparam [68:0] one69_lp = 1;
|
||||
localparam [69:0] one70_lp = 1;
|
||||
|
||||
bit all_ok = 1;
|
||||
|
||||
initial begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$display("one1_lp : %x %d", one1_lp, one1_lp==1);
|
||||
$display("one2_lp : %x %d", one2_lp, one2_lp==1);
|
||||
$display("one3_lp : %x %d", one3_lp, one3_lp==1);
|
||||
$display("one4_lp : %x %d", one4_lp, one4_lp==1);
|
||||
$display("one5_lp : %x %d", one5_lp, one5_lp==1);
|
||||
$display("one6_lp : %x %d", one6_lp, one6_lp==1);
|
||||
$display("one7_lp : %x %d", one7_lp, one7_lp==1);
|
||||
$display("one8_lp : %x %d", one8_lp, one8_lp==1);
|
||||
$display("one9_lp : %x %d", one9_lp, one9_lp==1);
|
||||
$display("one10_lp: %x %d", one10_lp, one10_lp==1);
|
||||
$display("one20_lp: %x %d", one20_lp, one20_lp==1);
|
||||
$display("one30_lp: %x %d", one30_lp, one30_lp==1);
|
||||
$display("one31_lp: %x %d", one31_lp, one31_lp==1);
|
||||
$display("one32_lp: %x %d", one32_lp, one32_lp==1);
|
||||
$display("one33_lp: %x %d", one33_lp, one33_lp==1);
|
||||
$display("one34_lp: %x %d", one34_lp, one34_lp==1);
|
||||
$display("one35_lp: %x %d", one35_lp, one35_lp==1);
|
||||
$display("one36_lp: %x %d", one36_lp, one36_lp==1);
|
||||
$display("one37_lp: %x %d", one37_lp, one37_lp==1);
|
||||
$display("one38_lp: %x %d", one38_lp, one38_lp==1);
|
||||
$display("one39_lp: %x %d", one39_lp, one39_lp==1);
|
||||
$display("one40_lp: %x %d", one40_lp, one40_lp==1);
|
||||
$display("one50_lp: %x %d", one50_lp, one50_lp==1);
|
||||
$display("one60_lp: %x %d", one60_lp, one60_lp==1);
|
||||
$display("one61_lp: %x %d", one61_lp, one61_lp==1);
|
||||
$display("one62_lp: %x %d", one62_lp, one62_lp==1);
|
||||
$display("one63_lp: %x %d", one63_lp, one63_lp==1);
|
||||
$display("one64_lp: %x %d", one64_lp, one64_lp==1);
|
||||
$display("one65_lp: %x %d", one65_lp, one65_lp==1);
|
||||
$display("one66_lp: %x %d", one66_lp, one66_lp==1);
|
||||
$display("one67_lp: %x %d", one67_lp, one67_lp==1);
|
||||
$display("one68_lp: %x %d", one68_lp, one68_lp==1);
|
||||
$display("one69_lp: %x %d", one69_lp, one69_lp==1);
|
||||
$display("one70_lp: %x %d", one70_lp, one70_lp==1);
|
||||
`endif
|
||||
|
||||
all_ok &= one1_lp == 1;
|
||||
all_ok &= one2_lp == 1;
|
||||
all_ok &= one3_lp == 1;
|
||||
all_ok &= one4_lp == 1;
|
||||
all_ok &= one5_lp == 1;
|
||||
all_ok &= one6_lp == 1;
|
||||
all_ok &= one7_lp == 1;
|
||||
all_ok &= one8_lp == 1;
|
||||
all_ok &= one9_lp == 1;
|
||||
all_ok &= one10_lp == 1;
|
||||
all_ok &= one20_lp == 1;
|
||||
all_ok &= one30_lp == 1;
|
||||
all_ok &= one31_lp == 1;
|
||||
all_ok &= one32_lp == 1;
|
||||
all_ok &= one33_lp == 1;
|
||||
all_ok &= one34_lp == 1;
|
||||
all_ok &= one35_lp == 1;
|
||||
all_ok &= one36_lp == 1;
|
||||
all_ok &= one37_lp == 1;
|
||||
all_ok &= one38_lp == 1;
|
||||
all_ok &= one39_lp == 1;
|
||||
all_ok &= one40_lp == 1;
|
||||
all_ok &= one50_lp == 1;
|
||||
all_ok &= one60_lp == 1;
|
||||
all_ok &= one61_lp == 1;
|
||||
all_ok &= one62_lp == 1;
|
||||
all_ok &= one63_lp == 1;
|
||||
all_ok &= one64_lp == 1;
|
||||
all_ok &= one65_lp == 1;
|
||||
all_ok &= one66_lp == 1;
|
||||
all_ok &= one67_lp == 1;
|
||||
all_ok &= one68_lp == 1;
|
||||
all_ok &= one69_lp == 1;
|
||||
all_ok &= one70_lp == 1;
|
||||
|
||||
if (!all_ok) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
||||
end
|
||||
endmodule
|
||||
|
||||
@@ -169,6 +169,10 @@
|
||||
`checkh(w32_u, 32'h0000_0180);
|
||||
w32_u = 32'(signed'({4'b0011,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
w32_u = signed'(32'({4'b0001,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0180);
|
||||
w32_u = signed'(32'({4'b0011,5'b10000}) << 3);
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
// verilator lint_on WIDTH
|
||||
w32_u = 32'(signed'({4'b0011,5'b10000})) << 3; // Check no width warning
|
||||
`checkh(w32_u, 32'h0000_0380);
|
||||
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/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,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
@@ -0,0 +1,27 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Wilson Snyder.
|
||||
|
||||
module t;
|
||||
function integer bottom_4bits;
|
||||
input [7:0] i;
|
||||
bottom_4bits = 0;
|
||||
bottom_4bits[3:0] = i[3:0];
|
||||
endfunction
|
||||
|
||||
function integer bottom_2_unknown;
|
||||
input [7:0] i;
|
||||
// bottom_4bits = 0; 'x
|
||||
bottom_2_unknown[1:0] = i[1:0];
|
||||
endfunction
|
||||
|
||||
localparam p = bottom_4bits(8'h13);
|
||||
localparam bu = bottom_2_unknown(8'h13);
|
||||
|
||||
initial begin
|
||||
if (p != 3) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
@@ -792,6 +792,13 @@ module t;
|
||||
|
||||
|
||||
initial $write("Slashed=`%s'\n", "1//2.3");
|
||||
|
||||
|
||||
|
||||
|
||||
initial
|
||||
`line 531 "t/t_preproc.v" 0
|
||||
$display("%s%s","a1","b2c3\n");
|
||||
endmodule
|
||||
|
||||
|
||||
@@ -813,4 +820,4 @@ predef 1 1
|
||||
predef 2 2
|
||||
|
||||
|
||||
`line 548 "t/t_preproc.v" 2
|
||||
`line 553 "t/t_preproc.v" 2
|
||||
|
||||
@@ -524,6 +524,11 @@ module t;
|
||||
// bug845
|
||||
`define SLASHED "1//2.3"
|
||||
initial $write("Slashed=`%s'\n", `SLASHED);
|
||||
//----
|
||||
// bug915
|
||||
`define BUG915(a,b,c) \
|
||||
$display("%s%s",a,`"b``c``\n`")
|
||||
initial `BUG915("a1",b2,c3);
|
||||
endmodule
|
||||
//======================================================================
|
||||
// IEEE mandated predefines
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
datarootdir=@datarootdir@
|
||||
includedir=@pkgdatadir@/include
|
||||
|
||||
Name: verilator
|
||||
Description: fast free Verilog simulator
|
||||
URL: http://www.veripool.org/verilator
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires:
|
||||
Libs:
|
||||
Cflags: -I${includedir} -I${includedir}/vltstd
|
||||
Reference in New Issue
Block a user