// -*- mode: C++; c-file-style: "cc-mode" -*- //************************************************************************* // DESCRIPTION: Verilator: File stream wrapper that understands indentation // // Code available from: http://www.veripool.org/verilator // //************************************************************************* // // Copyright 2003-2019 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. // // Verilator is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // //************************************************************************* #ifndef _V3FILE_H_ #define _V3FILE_H_ 1 #include "config_build.h" #include "verilatedos.h" #include "V3Error.h" #include #include #include #include //============================================================================ // V3File: Create streams, recording dependency information class V3File { public: static std::ifstream* new_ifstream(const string& filename) { addSrcDepend(filename); return new_ifstream_nodepend(filename); } static std::ifstream* new_ifstream_nodepend(const string& filename) { return new std::ifstream(filename.c_str()); } static std::ofstream* new_ofstream(const string& filename, bool append=false) { addTgtDepend(filename); return new_ofstream_nodepend(filename, append); } static std::ofstream* new_ofstream_nodepend(const string& filename, bool append=false) { if (filename != VL_DEV_NULL) createMakeDir(); if (append) { return new std::ofstream(filename.c_str(), std::ios::app); } else { return new std::ofstream(filename.c_str()); } } static FILE* new_fopen_w(const string& filename) { if (filename != VL_DEV_NULL) createMakeDir(); addTgtDepend(filename); return fopen(filename.c_str(), "w"); } // Dependencies static void addSrcDepend(const string& filename); static void addTgtDepend(const string& filename); static void writeDepend(const string& filename); static void writeTimes(const string& filename, const string& cmdlineIn); static bool checkTimes(const string& filename, const string& cmdlineIn); // Directory utilities static void createMakeDir(); }; //============================================================================ // V3InFilter: Read a input file, possibly filtering it, and caching contents class V3InFilterImp; class V3InFilter { public: // TYPES typedef std::list StrList; private: V3InFilterImp* m_impp; // CONSTRUCTORS VL_UNCOPYABLE(V3InFilter); public: explicit V3InFilter(const string& command); ~V3InFilter(); // METHODS // Read file contents and return it. Return true on success. bool readWholefile(const string& filename, StrList& outl); }; //============================================================================ // V3OutFormatter: A class for automatic indentation of C++ or Verilog code. class V3OutFormatter { // TYPES enum MiscConsts { MAXSPACE = 80}; // After this indent, stop indenting more public: enum AlignClass { AL_AUTO = 0, AL_STATIC = 1}; enum Language { LA_C = 0, LA_VERILOG = 1, LA_MK = 2, LA_XML = 3, }; private: // MEMBERS string m_filename; Language m_lang; // Indenting Verilog code int m_blockIndent; // Characters per block indent int m_commaWidth; // Width after which to break at ,'s int m_lineno; int m_column; int m_nobreak; // Basic operator or begin paren, don't break next bool m_prependIndent; int m_indentLevel; // Current {} indentation std::stack m_parenVec; // Stack of columns where last ( was int m_bracketLevel; // Intenting = { block, indicates number of {'s seen. int endLevels(const char* strg); const char* indentStr(int num); void putcNoTracking(char chr); public: V3OutFormatter(const string& filename, Language lang); virtual ~V3OutFormatter() {} // ACCESSORS int column() const { return m_column; } int blockIndent() const { return m_blockIndent; } void blockIndent(int flag) { m_blockIndent = flag; } // METHODS void printf(const char* fmt...) VL_ATTR_PRINTF(2); void puts(const char* strg); void puts(const string& strg) { puts(strg.c_str()); } void putsNoTracking(const string& strg); void putsQuoted(const string& strg); void putBreak(); // Print linebreak if line is too wide void putBreakExpr(); // Print linebreak in expression if line is too wide void putbs(const char* strg) { putBreakExpr(); puts(strg); } void putbs(const string& strg) { putBreakExpr(); puts(strg); } bool exceededWidth() const { return m_column > m_commaWidth; } bool tokenStart(const char* cp, const char* cmp); bool tokenEnd(const char* cp); void indentInc() { m_indentLevel += m_blockIndent; } void indentDec() { m_indentLevel -= m_blockIndent; UASSERT(m_indentLevel>=0, ": "<printf("%-19s\t%s;\n", classStar.c_str(), cellname.c_str()); } virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); } virtual void putsIntTopInclude() { putsForceIncs(); } // Print out public/privates void resetPrivate() { m_private = 0; } void putsPrivate(bool setPrivate) { if (setPrivate && m_private!=1) { puts("private:\n"); m_private = 1; } else if (!setPrivate && m_private!=2) { puts("public:\n"); m_private = 2; } } }; class V3OutScFile : public V3OutCFile { public: explicit V3OutScFile(const string& filename) : V3OutCFile(filename) {} virtual ~V3OutScFile() {} virtual void putsHeader() { puts("// Verilated -*- SystemC -*-\n"); } virtual void putsIntTopInclude() { putsForceIncs(); puts("#include \"systemc.h\"\n"); puts("#include \"verilated_sc.h\"\n"); } }; class V3OutVFile : public V3OutFile { public: explicit V3OutVFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_VERILOG) {} virtual ~V3OutVFile() {} virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); } }; class V3OutXmlFile : public V3OutFile { public: explicit V3OutXmlFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_XML) { blockIndent(2); } virtual ~V3OutXmlFile() {} virtual void putsHeader() { puts("\n"); } }; class V3OutMkFile : public V3OutFile { public: explicit V3OutMkFile(const string& filename) : V3OutFile(filename, V3OutFormatter::LA_MK) {} virtual ~V3OutMkFile() {} virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); } // No automatic indentation yet. void puts(const char* strg) { putsNoTracking(strg); } void puts(const string& strg) { putsNoTracking(strg); } }; #endif // Guard