Declare V3Tables static

git-svn-id: file://localhost/svn/verilator/trunk/verilator@763 77ca24e4-aefa-0310-84f0-b9a241c72d87
This commit is contained in:
Wilson Snyder 2006-08-29 00:58:48 +00:00
parent eec5c8bf6d
commit 3b09ceae12
4 changed files with 77 additions and 53 deletions

View File

@ -7,6 +7,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** Added --inhibit-sim flag for environments using old __Vm_inhibitSim. *** Added --inhibit-sim flag for environments using old __Vm_inhibitSim.
**** Declare tables static, to reduce D-Cache miss rate.
* Verilator 3.600 08/28/2006 * Verilator 3.600 08/28/2006
** Support dotted cross-hierarchy variable and task references. ** Support dotted cross-hierarchy variable and task references.

View File

@ -84,7 +84,7 @@ public:
void displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter); void displayArg(AstDisplay* dispp, AstNode** elistp, string fmt, char fmtLetter);
void emitVarDecl(AstVar* nodep, const string& prefixIfImp); void emitVarDecl(AstVar* nodep, const string& prefixIfImp);
typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_ALL} EisWhich; typedef enum {EVL_IO, EVL_SIG, EVL_TEMP, EVL_STATIC, EVL_ALL} EisWhich;
void emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp); void emitVarList(AstNode* firstp, EisWhich which, const string& prefixIfImp);
void emitVarCtors(); void emitVarCtors();
bool emitSimpleOk(AstNodeMath* nodep); bool emitSimpleOk(AstNodeMath* nodep);
@ -597,16 +597,16 @@ class EmitCImp : EmitCStmts {
+"<<endl; );\n"); +"<<endl; );\n");
if (nodep->initsp()) puts("// Variables\n"); if (nodep->initsp()) puts("// Variables\n");
ofp()->putAlign(4); ofp()->putAlign(V3OutFile::AL_AUTO, 4);
for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { for (AstNode* subnodep=nodep->argsp(); subnodep; subnodep = subnodep->nextp()) {
if (AstVar* varp=subnodep->castVar()) { if (AstVar* varp=subnodep->castVar()) {
if (varp->isFuncReturn()) emitVarDecl(varp, ""); if (varp->isFuncReturn()) emitVarDecl(varp, "");
} }
} }
emitVarList(nodep->initsp(), EVL_ALL, ""); emitVarList(nodep->initsp(), EVL_ALL, "");
ofp()->putAlign(4); ofp()->putAlign(V3OutFile::AL_AUTO, 4);
emitVarList(nodep->stmtsp(), EVL_ALL, ""); emitVarList(nodep->stmtsp(), EVL_ALL, "");
ofp()->putAlign(4); ofp()->putAlign(V3OutFile::AL_AUTO, 4);
nodep->initsp()->iterateAndNext(*this); nodep->initsp()->iterateAndNext(*this);
@ -693,7 +693,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
if (nodep->isIO()) { if (nodep->isIO()) {
if (nodep->isSc()) { if (nodep->isSc()) {
m_ctorVarsVec.push_back(nodep); m_ctorVarsVec.push_back(nodep);
ofp()->putAlign(4); // sc stuff is a structure, so bigger alignment ofp()->putAlign(nodep->isStatic(), 4); // sc stuff is a structure, so bigger alignment
if (nodep->attrScClocked() && nodep->isInput()) { if (nodep->attrScClocked() && nodep->isInput()) {
puts("sc_in_clk\t"); puts("sc_in_clk\t");
} else { } else {
@ -708,7 +708,7 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
puts(nodep->name()); puts(nodep->name());
puts(";\n"); puts(";\n");
} else { // C++ signals } else { // C++ signals
ofp()->putAlign(nodep->widthAlignBytes()); ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes());
if (nodep->isTristate()) puts("VL_INOUT"); if (nodep->isTristate()) puts("VL_INOUT");
else if (nodep->isInput()) puts("VL_IN"); else if (nodep->isInput()) puts("VL_IN");
else if (nodep->isOutput()) puts("VL_OUT"); else if (nodep->isOutput()) puts("VL_OUT");
@ -731,8 +731,8 @@ void EmitCStmts::emitVarDecl(AstVar* nodep, const string& prefixIfImp) {
} else { } else {
// Arrays need a small alignment, but may need different padding after. // Arrays need a small alignment, but may need different padding after.
// For example three VL_SIG8's needs alignment 1 but size 3. // For example three VL_SIG8's needs alignment 1 but size 3.
ofp()->putAlign(nodep->widthAlignBytes(), nodep->arrayElements()*nodep->widthAlignBytes()); ofp()->putAlign(nodep->isStatic(), nodep->widthAlignBytes(), nodep->arrayElements()*nodep->widthAlignBytes());
// if (nodep->isStatic()) puts("static "); // Need implementation declaration too - prefixIfImp is start in this direction if (nodep->isStatic() && prefixIfImp=="") puts("static ");
if (nodep->widthMin() <= 8) { if (nodep->widthMin() <= 8) {
puts("VL_SIG8("); puts("VL_SIG8(");
} else if (nodep->widthMin() <= 16) { } else if (nodep->widthMin() <= 16) {
@ -1109,7 +1109,7 @@ void EmitCImp::emitCoverageDecl(AstModule* modp) {
ofp()->putsPrivate(true); ofp()->putsPrivate(true);
puts("// Coverage\n"); puts("// Coverage\n");
puts("SpZeroed<uint32_t>\t__Vcoverage["); puts(cvtToStr(m_coverIds.size())); puts("];\n"); puts("SpZeroed<uint32_t>\t__Vcoverage["); puts(cvtToStr(m_coverIds.size())); puts("];\n");
ofp()->putAlign(sizeof(uint32_t)*m_coverIds.size()); ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(uint32_t)*m_coverIds.size());
// Rather then putting out SP_COVER_INSERT calls directly, we do it via this function // Rather then putting out SP_COVER_INSERT calls directly, we do it via this function
// This gets around gcc slowness constructing all of the template arguments // This gets around gcc slowness constructing all of the template arguments
puts("void _vlCoverInsert(SpZeroed<uint32_t>* countp, const char* filename, int lineno, int column,\n"); puts("void _vlCoverInsert(SpZeroed<uint32_t>* countp, const char* filename, int lineno, int column,\n");
@ -1239,35 +1239,41 @@ void EmitCStmts::emitVarList(AstNode* firstp, EisWhich which, const string& pref
// Put out a list of signal declarations // Put out a list of signal declarations
// in order of 0:clocks, 1:uint8, 2:uint16, 4:uint32, 5:uint64, 6:wide, 7:arrays // in order of 0:clocks, 1:uint8, 2:uint16, 4:uint32, 5:uint64, 6:wide, 7:arrays
// This aids cache packing and locality // This aids cache packing and locality
for (int size=0; size<8; size++) { // Largest->smallest reduces the number of pad variables.
if (size==3) continue; // But for now, Smallest->largest makes it more likely a small offset will allow access to the signal.
for (AstNode* nodep=firstp; nodep; nodep = nodep->nextp()) { for (int isstatic=1; isstatic>=0; isstatic--) {
if (AstVar* varp = nodep->castVar()) { if (prefixIfImp!="" && !isstatic) continue;
bool doit = true; for (int size=0; size<8; size++) {
switch (which) { if (size==3) continue;
case EVL_ALL: doit = true; break; for (AstNode* nodep=firstp; nodep; nodep = nodep->nextp()) {
case EVL_IO: doit = varp->isIO(); break; if (AstVar* varp = nodep->castVar()) {
case EVL_SIG: doit = (varp->isSignal() && !varp->isIO()); break; bool doit = true;
case EVL_TEMP: doit = varp->isTemp(); break; switch (which) {
default: v3fatalSrc("Bad Case"); case EVL_ALL: doit = true; break;
} case EVL_IO: doit = varp->isIO(); break;
if (doit) { case EVL_SIG: doit = (varp->isSignal() && !varp->isIO()); break;
int sigbytes = varp->widthAlignBytes(); case EVL_TEMP: doit = varp->isTemp(); break;
if (varp->isUsedClock() && varp->widthMin()==1) sigbytes = 0; default: v3fatalSrc("Bad Case");
else if (varp->arraysp()) sigbytes=7; }
else if (varp->isScWide()) sigbytes=6; if (varp->isStatic() ? !isstatic : isstatic) doit=false;
else if (sigbytes==8) sigbytes=5; if (doit) {
else if (sigbytes==4) sigbytes=4; int sigbytes = varp->widthAlignBytes();
else if (sigbytes==2) sigbytes=2; if (varp->isUsedClock() && varp->widthMin()==1) sigbytes = 0;
else if (sigbytes==1) sigbytes=1; else if (varp->arraysp()) sigbytes=7;
if (size==sigbytes) { else if (varp->isScWide()) sigbytes=6;
emitVarDecl(varp, prefixIfImp); else if (sigbytes==8) sigbytes=5;
else if (sigbytes==4) sigbytes=4;
else if (sigbytes==2) sigbytes=2;
else if (sigbytes==1) sigbytes=1;
if (size==sigbytes) {
emitVarDecl(varp, prefixIfImp);
}
} }
} }
} }
} }
ofp()->putAlign(isstatic, 4, 0, prefixIfImp.c_str());
} }
ofp()->putAlign(4, 0, prefixIfImp.c_str());
} }
struct CmpName { struct CmpName {
@ -1354,22 +1360,22 @@ void EmitCImp::emitInt(AstModule* modp) {
puts("\n// INTERNAL VARIABLES\n"); puts("\n// INTERNAL VARIABLES\n");
ofp()->putsPrivate(!modp->isTop()); // private: unless top ofp()->putsPrivate(!modp->isTop()); // private: unless top
ofp()->putAlign(8); ofp()->putAlign(V3OutFile::AL_AUTO, 8);
puts(symClassName()+"*\t__VlSymsp;\t\t// Symbol table\n"); puts(symClassName()+"*\t__VlSymsp;\t\t// Symbol table\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
if (modp->isTop()) { if (modp->isTop()) {
if (v3Global.opt.inhibitSim()) { if (v3Global.opt.inhibitSim()) {
ofp()->putAlign(sizeof(bool)); ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n"); puts("bool\t__Vm_inhibitSim;\t///< Set true to disable evaluation of module\n");
} }
ofp()->putAlign(sizeof(bool)); ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n"); puts("bool\t__Vm_activity;\t\t///< Used by trace routines to determine change occurred\n");
ofp()->putAlign(sizeof(bool)); ofp()->putAlign(V3OutFile::AL_AUTO, sizeof(bool));
puts("bool\t__Vm_didInit;\n"); puts("bool\t__Vm_didInit;\n");
} }
ofp()->putAlign(8); ofp()->putAlign(V3OutFile::AL_AUTO, 8);
emitCoverageDecl(modp); // may flip public/private emitCoverageDecl(modp); // may flip public/private
ofp()->putAlign(8); ofp()->putAlign(V3OutFile::AL_AUTO, 8);
puts("\n// PARAMETERS\n"); puts("\n// PARAMETERS\n");
ofp()->putsPrivate(false); // public: ofp()->putsPrivate(false); // public:
@ -1482,6 +1488,13 @@ void EmitCImp::emitImp(AstModule* modp) {
} }
emitTextSection(AstType::SCIMPHDR); emitTextSection(AstType::SCIMPHDR);
if (m_slow && m_splitFilenum==0) {
puts("\n//--------------------\n");
puts("// STATIC VARIABLES\n\n");
emitVarList(modp->stmtsp(), EVL_ALL, modClassName(modp));
}
if (m_fast && m_splitFilenum==0) { if (m_fast && m_splitFilenum==0) {
emitTextSection(AstType::SCIMP); emitTextSection(AstType::SCIMP);
emitStaticDecl(modp); emitStaticDecl(modp);
@ -1770,7 +1783,7 @@ class EmitCTrace : EmitCStmts {
if (nodep->initsp()) puts("// Variables\n"); if (nodep->initsp()) puts("// Variables\n");
emitVarList(nodep->initsp(), EVL_ALL, ""); emitVarList(nodep->initsp(), EVL_ALL, "");
nodep->initsp()->iterateAndNext(*this); nodep->initsp()->iterateAndNext(*this);
ofp()->putAlign(4); ofp()->putAlign(V3OutFile::AL_AUTO, 4);
puts("// Body\n"); puts("// Body\n");
puts("{\n"); puts("{\n");

View File

@ -225,7 +225,7 @@ bool V3File::checkTimes(const string& filename, const string& cmdline) {
V3OutFile::V3OutFile(const string& filename) V3OutFile::V3OutFile(const string& filename)
: m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0) : m_lineno(1), m_column(0), m_nobreak(false), m_prependIndent(true), m_indentLevel(0)
, m_declAlign(0), m_declPadNum(0) { , m_declSAlign(0), m_declNSAlign(0), m_declPadNum(0) {
if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) { if ((m_fp = V3File::new_fopen_w(filename.c_str())) == NULL) {
v3fatal("Cannot write "<<filename); v3fatal("Cannot write "<<filename);
} }
@ -440,19 +440,20 @@ void V3OutFile::putcNoTracking (char chr) {
fputc (chr, m_fp); fputc (chr, m_fp);
} }
void V3OutFile::putAlign (int align, int size, const char* prefix) { void V3OutFile::putAlign (bool/*AlignClass*/ isStatic, int align, int size, const char* prefix) {
if (size==0) size=align; if (size==0) size=align;
int alignSize = size; if (alignSize>8) alignSize=8; int alignSize = size; if (alignSize>8) alignSize=8;
int padsize = alignSize - (m_declAlign % alignSize); int& alignr = isStatic ? m_declSAlign : m_declNSAlign;
int padsize = alignSize - (alignr % alignSize);
if (padsize && padsize!=alignSize) { if (padsize && padsize!=alignSize) {
puts("char\t"); puts("char\t");
puts(prefix); puts(prefix);
puts("__VpadToAlign"+cvtToStr(m_declPadNum) puts("__VpadToAlign"+cvtToStr(alignr)
+"["+cvtToStr(padsize)+"];\n"); +"["+cvtToStr(padsize)+"];\n");
m_declAlign += padsize; alignr += padsize;
m_declPadNum++; m_declPadNum++;
} }
m_declAlign += size; alignr += size;
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

View File

@ -64,24 +64,32 @@ public:
// V3OutFile: A class for printing to a file, with automatic indentation of C++ code. // V3OutFile: A class for printing to a file, with automatic indentation of C++ code.
class V3OutFile { class V3OutFile {
// TYPES
enum MiscConsts {
INDBLK = 4, // Indentation per block level
WIDTH = 50, // Width after which to break at ,'s
MAXSPACE = 80}; // After this indent, stop indenting more
public:
enum AlignClass {
AL_AUTO = 0,
AL_STATIC = 1};
private:
// MEMBERS
FILE* m_fp; FILE* m_fp;
int m_lineno; int m_lineno;
int m_column; int m_column;
int m_nobreak; // Basic operator or begin paren, don't break next int m_nobreak; // Basic operator or begin paren, don't break next
bool m_prependIndent; bool m_prependIndent;
int m_indentLevel; // Current {} indentation int m_indentLevel; // Current {} indentation
int m_declAlign; // Byte alignment of next declaration int m_declSAlign; // Byte alignment of next declaration, statics
int m_declNSAlign; // Byte alignment of next declaration, nonstatics
int m_declPadNum; // Pad variable number int m_declPadNum; // Pad variable number
stack<int> m_parenVec; // Stack of columns where last ( was stack<int> m_parenVec; // Stack of columns where last ( was
int endLevels(const char* strg); int endLevels(const char* strg);
static const char* indentStr(int levels); static const char* indentStr(int levels);
enum MiscConsts {
INDBLK = 4, // Indentation per block level
WIDTH = 50, // Width after which to break at ,'s
MAXSPACE = 80}; // After this indent, stop indenting more
public: public:
V3OutFile(const string& filename); V3OutFile(const string& filename);
~V3OutFile(); ~V3OutFile();
@ -95,7 +103,7 @@ public:
void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); } void putsNoTracking(const string& strg) { putsNoTracking(strg.c_str()); }
void putBreak(); // Print linebreak if line is too wide void putBreak(); // Print linebreak if line is too wide
void putBreakExpr(); // Print linebreak in expression if line is too wide void putBreakExpr(); // Print linebreak in expression if line is too wide
void putAlign(int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment void putAlign(bool isstatic/*AlignClass*/, int align, int size=0/*=align*/, const char* prefix=""); // Declare a variable, with natural alignment
void putbs(const char* strg) { putBreakExpr(); puts(strg); } void putbs(const char* strg) { putBreakExpr(); puts(strg); }
void putbs(const string& strg) { putBreakExpr(); puts(strg); } void putbs(const string& strg) { putBreakExpr(); puts(strg); }
bool exceededWidth() const { return m_column > WIDTH; } bool exceededWidth() const { return m_column > WIDTH; }