From 77915f78db5ec8b0e8ab8a52ff8aa9b374fc646a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 21 Apr 2020 20:45:23 -0400 Subject: [PATCH] Add experimental-only option. --- src/Makefile_obj.in | 1 + src/V3EmitCMain.cpp | 100 ++++++++++++++++++++++++++++++++++ src/V3EmitCMain.h | 30 ++++++++++ src/V3Options.cpp | 11 +++- src/V3Options.h | 2 + src/Verilator.cpp | 10 ++-- test_regress/t/t_flag_main.pl | 26 +++++++++ test_regress/t/t_flag_main.v | 13 +++++ 8 files changed, 185 insertions(+), 8 deletions(-) create mode 100644 src/V3EmitCMain.cpp create mode 100644 src/V3EmitCMain.h create mode 100755 test_regress/t/t_flag_main.pl create mode 100644 test_regress/t/t_flag_main.v diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index f35bb2103..911f97e1f 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -185,6 +185,7 @@ RAW_OBJS = \ V3EmitCInlines.o \ V3EmitCSyms.o \ V3EmitCMake.o \ + V3EmitCMain.o \ V3EmitMk.o \ V3EmitV.o \ V3EmitXml.o \ diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp new file mode 100644 index 000000000..14e67ed2a --- /dev/null +++ b/src/V3EmitCMain.cpp @@ -0,0 +1,100 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Emit C++ for tree +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2020 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. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3Global.h" +#include "V3EmitC.h" +#include "V3EmitCBase.h" +#include "V3EmitCMain.h" + +#include +#include +#include +#include + +//###################################################################### + +class EmitCMain : EmitCBaseVisitor { + // METHODS + + // VISITORS + virtual void visit(AstNode* nodep) { iterateChildren(nodep); } + +public: + // CONSTRUCTORS + explicit EmitCMain(AstNetlist* nodep) { emitInt(); } + +private: + // MAIN METHOD + void emitInt() { + string filename = v3Global.opt.makeDir() + "/" + topClassName() + "__main.cpp"; + newCFile(filename, false /*slow*/, true /*source*/); + V3OutCFile cf(filename); + m_ofp = &cf; + + // Heavly commented output, as users are likely to look at or copy this code + ofp()->putsHeader(); + puts("// DESCRIPTION: main() calling loop, created with Verilator --main\n"); + puts("\n"); + + puts("#include \"verilated.h\"\n"); + puts("#include \"" + topClassName() + ".h\"\n"); + + puts("\n//======================\n\n"); + + puts(topClassName() + "* topp;\n"); + puts("\n"); + puts("// Requires -DVL_TIME_STAMP64\n"); + v3Global.opt.addCFlags("-DVL_TIME_STAMP64"); + puts("vluint64_t main_time = 0;\n"); + puts("vluint64_t vl_time_stamp64() { return main_time; }\n"); + puts("\n"); + + puts("int main(int argc, char** argv, char**) {\n"); + puts("// Setup defaults and parse command line\n"); + puts("Verilated::debug(0);\n"); + puts("Verilated::commandArgs(argc, argv);\n"); + puts("// Construct the Verilated model, from Vtop.h generated from Verilating\n"); + puts("topp = new " + topClassName() + "(\"top\");\n"); + puts("// Evaluate initials\n"); + puts("topp->eval(); // Evaluate\n"); + + puts("// Simulate until $finish\n"); + puts("while (!Verilated::gotFinish()) {\n"); + /**/ puts("// Evaluate model\n"); + /**/ puts("topp->eval();\n"); + /**/ puts("// Advance time\n"); + /**/ puts("++main_time;\n"); + puts("}\n"); + puts("\n"); + + puts("// Final model cleanup\n"); + puts("topp->final();\n"); + puts("VL_DO_DANGLING(delete topp, topp);\n"); + puts("exit(0);\n"); + puts("}\n"); + } +}; + +//###################################################################### +// EmitC class functions + +void V3EmitCMain::emit() { + UINFO(2, __FUNCTION__ << ": " << endl); + EmitCMain(v3Global.rootp()); +} diff --git a/src/V3EmitCMain.h b/src/V3EmitCMain.h new file mode 100644 index 000000000..04df088a2 --- /dev/null +++ b/src/V3EmitCMain.h @@ -0,0 +1,30 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Emit C main() +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2020 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. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#ifndef _V3EMITCMAIN_H_ +#define _V3EMITCMAIN_H_ 1 + +#include "config_build.h" +#include "verilatedos.h" + +//============================================================================ + +class V3EmitCMain { +public: + static void emit(); +}; + +#endif // Guard diff --git a/src/V3Options.cpp b/src/V3Options.cpp index c836bffc6..1d4000b87 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -585,6 +585,8 @@ string V3Options::getenvVERILATOR_ROOT() { // V3 Options notification methods void V3Options::notify() { + FileLine* cmdfl = new FileLine(FileLine::commandLineFilename()); + // Notify that all arguments have been passed and final modification can be made. if (!outFormatOk() && !cdc() && !dpiHdrOnly() && !lintOnly() && !preprocOnly() && !xmlOnly()) { v3fatal("verilator: Need --cc, --sc, --cdc, --dpi-hdr-only, --lint-only, " @@ -595,7 +597,6 @@ void V3Options::notify() { if (!m_gmake && !m_cmake) m_gmake = true; if (protectIds()) { - FileLine* cmdfl = new FileLine(FileLine::commandLineFilename()); if (allPublic()) { // We always call protect() on names, we don't check if public or not // Hence any external references wouldn't be able to find the refed public object. @@ -633,7 +634,11 @@ void V3Options::notify() { } // --trace-threads implies --threads 1 unless explicitly specified - if (traceThreads() && !threads()) { m_threads = 1; } + if (traceThreads() && !threads()) m_threads = 1; + + if (v3Global.opt.main() && v3Global.opt.systemC()) { + cmdfl->v3error("--main not usable with SystemC. Suggest see examples for sc_main()."); + } } //###################################################################### @@ -849,6 +854,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-ignc", flag/*ref*/)) { m_ignc = flag; } else if ( onoff (sw, "-inhibit-sim", flag/*ref*/)) { m_inhibitSim = flag; } else if ( onoff (sw, "-lint-only", flag/*ref*/)) { m_lintOnly = flag; } + else if ( onoff (sw, "-main", flag/*ref*/)) { m_main = flag; } // Undocumented future else if (!strcmp(sw, "-no-pins64")) { m_pinsBv = 33; } else if ( onoff (sw, "-order-clock-delay", flag/*ref*/)) { m_orderClockDly = flag; } else if (!strcmp(sw, "-pins64")) { m_pinsBv = 65; } @@ -1543,6 +1549,7 @@ V3Options::V3Options() { m_lintOnly = false; m_gmake = false; m_makePhony = false; + m_main = false; m_orderClockDly = true; m_outFormatOk = false; m_pedantic = false; diff --git a/src/V3Options.h b/src/V3Options.h index 2e48eda40..6e4941ba8 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -234,6 +234,7 @@ private: bool m_inhibitSim; // main switch: --inhibit-sim bool m_lintOnly; // main switch: --lint-only bool m_gmake; // main switch: --make gmake + bool m_main; // main swithc: --main bool m_orderClockDly;// main switch: --order-clock-delay bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified bool m_pedantic; // main switch: --Wpedantic @@ -436,6 +437,7 @@ public: bool traceParams() const { return m_traceParams; } bool traceStructs() const { return m_traceStructs; } bool traceUnderscore() const { return m_traceUnderscore; } + bool main() const { return m_main; } bool orderClockDly() const { return m_orderClockDly; } bool outFormatOk() const { return m_outFormatOk; } bool keepTempFiles() const { return (V3Error::debugDefault() != 0); } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 31a499e28..c34bd6b6a 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -42,6 +42,7 @@ #include "V3Descope.h" #include "V3EmitC.h" #include "V3EmitCMake.h" +#include "V3EmitCMain.h" #include "V3EmitMk.h" #include "V3EmitV.h" #include "V3EmitXml.h" @@ -487,12 +488,9 @@ static void process() { if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && !v3Global.opt.dpiHdrOnly()) { // Makefile must be after all other emitters - if (v3Global.opt.cmake()) { // - V3EmitCMake::emit(); - } - if (v3Global.opt.gmake()) { // - V3EmitMk::emitmk(); - } + if (v3Global.opt.main()) V3EmitCMain::emit(); + if (v3Global.opt.cmake()) V3EmitCMake::emit(); + if (v3Global.opt.gmake()) V3EmitMk::emitmk(); } // Note early return above when opt.cdc() diff --git a/test_regress/t/t_flag_main.pl b/test_regress/t/t_flag_main.pl new file mode 100755 index 000000000..e68010553 --- /dev/null +++ b/test_regress/t/t_flag_main.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + verilator_flags2 => ['--exe --build --main'], + verilator_make_cmake => 0, + verilator_make_gmake => 0, + make_main => 0, + make_top => 1, + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_flag_main.v b/test_regress/t/t_flag_main.v new file mode 100644 index 000000000..ef63ab8ca --- /dev/null +++ b/test_regress/t/t_flag_main.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by engr248. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + initial begin + $write("[%0t] Hello", $time); // Check timestamp works + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule