2012-04-13 01:08:20 +00:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 11:35:28 +00:00
|
|
|
//*************************************************************************
|
|
|
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
|
|
|
//
|
2019-11-08 03:33:59 +00:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
//
|
2021-01-01 15:29:54 +00:00
|
|
|
// Copyright 2003-2021 by Wilson Snyder. This program is free software; you
|
2020-03-21 15:24:24 +00:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 21:07:57 +00:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
// Version 2.0.
|
2020-03-21 15:24:24 +00:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
2019-10-05 00:17:11 +00:00
|
|
|
|
2021-03-04 02:57:07 +00:00
|
|
|
#ifndef VERILATOR_V3EMITCBASE_H_
|
|
|
|
#define VERILATOR_V3EMITCBASE_H_
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
#include "config_build.h"
|
|
|
|
#include "verilatedos.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
#include "V3File.h"
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
2018-10-14 17:43:24 +00:00
|
|
|
#include <cstdarg>
|
|
|
|
#include <cmath>
|
|
|
|
|
2021-07-22 14:53:42 +00:00
|
|
|
//######################################################################
|
|
|
|
// Set user4p in all CFunc and Var to point to the containing AstNodeModule
|
|
|
|
|
|
|
|
class EmitCParentModule final {
|
|
|
|
// NODE STATE
|
|
|
|
// AstFunc::user4p() AstNodeModule* Parent module pointer
|
|
|
|
// AstVar::user4p() AstNodeModule* Parent module pointer
|
|
|
|
AstUser4InUse user4InUse;
|
|
|
|
|
|
|
|
public:
|
|
|
|
EmitCParentModule();
|
|
|
|
VL_UNCOPYABLE(EmitCParentModule);
|
|
|
|
|
|
|
|
static const AstNodeModule* get(const AstNode* nodep) {
|
2021-10-22 14:15:42 +00:00
|
|
|
return VN_AS(nodep->user4p(), NodeModule);
|
2021-07-22 14:53:42 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
//######################################################################
|
|
|
|
// Base Visitor class -- holds output file pointer
|
|
|
|
|
2020-11-19 02:32:16 +00:00
|
|
|
class EmitCBaseVisitor VL_NOT_FINAL : public AstNVisitor {
|
2006-08-26 11:35:28 +00:00
|
|
|
public:
|
|
|
|
// STATE
|
2020-08-15 17:11:27 +00:00
|
|
|
V3OutCFile* m_ofp = nullptr;
|
|
|
|
bool m_trackText = false; // Always track AstText nodes
|
2006-08-26 11:35:28 +00:00
|
|
|
// METHODS
|
2019-05-19 20:13:13 +00:00
|
|
|
V3OutCFile* ofp() const { return m_ofp; }
|
2006-08-26 11:35:28 +00:00
|
|
|
void puts(const string& str) { ofp()->puts(str); }
|
|
|
|
void putbs(const string& str) { ofp()->putbs(str); }
|
2020-04-15 11:58:34 +00:00
|
|
|
void putsDecoration(const string& str) {
|
|
|
|
if (v3Global.opt.decoration()) puts(str);
|
|
|
|
}
|
2009-05-08 17:16:19 +00:00
|
|
|
void putsQuoted(const string& str) { ofp()->putsQuoted(str); }
|
2021-06-13 13:33:11 +00:00
|
|
|
void ensureNewLine() { ofp()->ensureNewLine(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
bool optSystemC() { return v3Global.opt.systemC(); }
|
2019-10-06 17:24:21 +00:00
|
|
|
static string protect(const string& name) { return VIdProtect::protectIf(name, true); }
|
|
|
|
static string protectIf(const string& name, bool doIt) {
|
2020-04-15 11:58:34 +00:00
|
|
|
return VIdProtect::protectIf(name, doIt);
|
|
|
|
}
|
2019-10-06 17:24:21 +00:00
|
|
|
static string protectWordsIf(const string& name, bool doIt) {
|
2020-04-15 11:58:34 +00:00
|
|
|
return VIdProtect::protectWordsIf(name, doIt);
|
|
|
|
}
|
2019-10-06 17:24:21 +00:00
|
|
|
static string ifNoProtect(const string& in) { return v3Global.opt.protectIds() ? "" : in; }
|
Introduce model interface class, make $root part or Syms (#3036)
This patch implements #3032. Verilator creates a module representing the
SystemVerilog $root scope (V3LinkLevel::wrapTop). Until now, this was
called the "TOP" module, which also acted as the user instantiated model
class. Syms used to hold a pointer to this root module, but hold
instances of any submodule. This patch renames this root scope module
from "TOP" to "$root", and introduces a separate model class which is
now an interface class. As the root module is no longer the user
interface class, it can now be made an instance of Syms, just like any
other submodule. This allows absolute references into the root module to
avoid an additional pointer indirection resulting in a potential speedup
(about 1.5% on OpenTitan). The model class now also contains all non
design specific generated code (e.g.: eval loops, trace config, etc),
which additionally simplifies Verilator internals.
Please see the updated documentation for the model interface changes.
2021-06-21 14:30:20 +00:00
|
|
|
static string voidSelfAssign(const AstNodeModule* modp) {
|
|
|
|
const string className = prefixNameProtect(modp);
|
|
|
|
return className + "* const __restrict vlSelf VL_ATTR_UNUSED = static_cast<" + className
|
|
|
|
+ "*>(voidSelf);\n";
|
2021-06-16 11:18:56 +00:00
|
|
|
}
|
2020-04-15 11:58:34 +00:00
|
|
|
static string symClassName() { return v3Global.opt.prefix() + "_" + protect("_Syms"); }
|
|
|
|
static string symClassVar() { return symClassName() + "* __restrict vlSymsp"; }
|
2021-06-13 13:33:11 +00:00
|
|
|
static string symClassAssign() {
|
|
|
|
return symClassName() + "* const __restrict vlSymsp VL_ATTR_UNUSED = vlSelf->vlSymsp;\n";
|
2020-04-15 11:58:34 +00:00
|
|
|
}
|
2021-06-24 15:58:30 +00:00
|
|
|
static string funcNameProtect(const AstCFunc* nodep, const AstNodeModule* modp = nullptr);
|
2020-01-25 14:16:00 +00:00
|
|
|
static string prefixNameProtect(const AstNode* nodep) { // C++ name with prefix
|
Introduce model interface class, make $root part or Syms (#3036)
This patch implements #3032. Verilator creates a module representing the
SystemVerilog $root scope (V3LinkLevel::wrapTop). Until now, this was
called the "TOP" module, which also acted as the user instantiated model
class. Syms used to hold a pointer to this root module, but hold
instances of any submodule. This patch renames this root scope module
from "TOP" to "$root", and introduces a separate model class which is
now an interface class. As the root module is no longer the user
interface class, it can now be made an instance of Syms, just like any
other submodule. This allows absolute references into the root module to
avoid an additional pointer indirection resulting in a potential speedup
(about 1.5% on OpenTitan). The model class now also contains all non
design specific generated code (e.g.: eval loops, trace config, etc),
which additionally simplifies Verilator internals.
Please see the updated documentation for the model interface changes.
2021-06-21 14:30:20 +00:00
|
|
|
return v3Global.opt.modPrefix() + "_" + protect(nodep->name());
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2019-05-19 20:13:13 +00:00
|
|
|
static string topClassName() { // Return name of top wrapper module
|
|
|
|
return v3Global.opt.prefix();
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2021-06-13 14:05:55 +00:00
|
|
|
|
2021-07-20 12:55:38 +00:00
|
|
|
static bool isConstPoolMod(const AstNode* modp) {
|
2021-06-13 14:05:55 +00:00
|
|
|
return modp == v3Global.rootp()->constPoolp()->modp();
|
|
|
|
}
|
|
|
|
|
Add V3VariableOrder pass
A separate V3VariableOrder pass is now used to order module variables
before Emit. All variables are now ordered together, without
consideration for whether they are ports, signals form the design, or
additional internal variables added by Verilator (which used to be
ordered and emitted as separate groups in Emit). For single threaded
models, this is performance neutral. For multi-threaded models, the
MTask affinity based sorting was slightly modified, so variables with no
MTask affinity are emitted last, otherwise the MTask affinity sets are
sorted using the TSP sorter as before, but again, ports, signals, and
internal variables are not differentiated. This yields a 2%+ speedup for
the multithreaded model on OpenTitan.
2021-06-29 16:57:07 +00:00
|
|
|
static bool isAnonOk(const AstVar* varp) {
|
|
|
|
return v3Global.opt.compLimitMembers() != 0 // Enabled
|
|
|
|
&& !varp->isStatic() // Not a static variable
|
|
|
|
&& !varp->isSc() // Aggregates can't be anon
|
|
|
|
&& (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon
|
|
|
|
}
|
|
|
|
|
2021-06-24 15:58:30 +00:00
|
|
|
static AstCFile* newCFile(const string& filename, bool slow, bool source);
|
|
|
|
string cFuncArgs(const AstCFunc* nodep);
|
|
|
|
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
|
|
|
|
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
|
Add V3VariableOrder pass
A separate V3VariableOrder pass is now used to order module variables
before Emit. All variables are now ordered together, without
consideration for whether they are ports, signals form the design, or
additional internal variables added by Verilator (which used to be
ordered and emitted as separate groups in Emit). For single threaded
models, this is performance neutral. For multi-threaded models, the
MTask affinity based sorting was slightly modified, so variables with no
MTask affinity are emitted last, otherwise the MTask affinity sets are
sorted using the TSP sorter as before, but again, ports, signals, and
internal variables are not differentiated. This yields a 2%+ speedup for
the multithreaded model on OpenTitan.
2021-06-29 16:57:07 +00:00
|
|
|
void emitVarDecl(const AstVar* nodep, bool asRef = false);
|
2021-07-07 18:16:40 +00:00
|
|
|
void emitModCUse(const AstNodeModule* modp, VUseType useType);
|
|
|
|
void emitTextSection(const AstNodeModule* modp, AstType type);
|
2021-06-13 13:33:11 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
// CONSTRUCTORS
|
2020-11-17 00:56:16 +00:00
|
|
|
EmitCBaseVisitor() = default;
|
|
|
|
virtual ~EmitCBaseVisitor() override = default;
|
2006-08-26 11:35:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//######################################################################
|
2008-11-17 22:13:57 +00:00
|
|
|
// Count operations under the given node, as a visitor of each AstNode
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2020-11-19 02:32:16 +00:00
|
|
|
class EmitCBaseCounterVisitor final : public AstNVisitor {
|
2006-08-26 11:35:28 +00:00
|
|
|
private:
|
2019-05-19 20:13:13 +00:00
|
|
|
// MEMBERS
|
2020-08-16 13:55:36 +00:00
|
|
|
int m_count = 0; // Number of statements
|
2006-08-26 11:35:28 +00:00
|
|
|
// VISITORS
|
2020-08-15 14:03:34 +00:00
|
|
|
virtual void visit(AstNode* nodep) override {
|
2021-07-23 23:24:25 +00:00
|
|
|
++m_count;
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-04-15 11:58:34 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
public:
|
2019-09-12 11:22:22 +00:00
|
|
|
// CONSTRUCTORS
|
2020-08-16 13:55:36 +00:00
|
|
|
explicit EmitCBaseCounterVisitor(AstNode* nodep) { iterate(nodep); }
|
2020-11-17 00:56:16 +00:00
|
|
|
virtual ~EmitCBaseCounterVisitor() override = default;
|
2006-08-26 11:35:28 +00:00
|
|
|
int count() const { return m_count; }
|
|
|
|
};
|
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
#endif // guard
|