2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 13:35:28 +02:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Emit Makefile
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2023-01-01 16:18:39 +01:00
|
|
|
// Copyright 2004-2023 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2023-09-25 04:12:23 +02:00
|
|
|
#define VL_MT_DISABLED_CODE_UNIT 1
|
|
|
|
|
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2022-08-05 11:56:57 +02:00
|
|
|
#include "V3EmitMk.h"
|
|
|
|
|
|
|
|
|
|
#include "V3EmitCBase.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
#include "V3Global.h"
|
2020-08-15 15:43:53 +02:00
|
|
|
#include "V3HierBlock.h"
|
2015-02-27 02:40:45 +01:00
|
|
|
#include "V3Os.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2022-09-18 21:53:42 +02:00
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
|
|
2022-10-12 11:19:21 +02:00
|
|
|
// ######################################################################
|
|
|
|
|
// Emit statements and expressions
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class EmitMk final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
|
|
|
|
// METHODS
|
2009-01-21 22:56:50 +01:00
|
|
|
|
2009-12-03 03:15:56 +01:00
|
|
|
void putMakeClassEntry(V3OutMkFile& of, const string& name) {
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("\t" + V3Os::filenameNonDirExt(name) + " \\\n");
|
2009-12-03 03:15:56 +01:00
|
|
|
}
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
void emitClassMake() {
|
2019-05-19 22:13:13 +02:00
|
|
|
// Generate the makefile
|
2022-11-20 19:11:01 +01:00
|
|
|
V3OutMkFile of{v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_classes.mk"};
|
2019-05-19 22:13:13 +02:00
|
|
|
of.putsHeader();
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("# DESCR"
|
|
|
|
|
"IPTION: Verilator output: Make include file with class lists\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("#\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("# This file lists generated Verilated files, for including "
|
|
|
|
|
"in higher level makefiles.\n");
|
|
|
|
|
of.puts("# See " + v3Global.opt.prefix() + ".mk" + " for the caller.\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
|
|
|
|
|
of.puts("\n### Switches...\n");
|
2020-08-16 21:10:43 +02:00
|
|
|
of.puts("# C11 constructs required? 0/1 (always on now)\n");
|
|
|
|
|
of.puts("VM_C11 = 1\n");
|
Timing support (#3363)
Adds timing support to Verilator. It makes it possible to use delays,
event controls within processes (not just at the start), wait
statements, and forks.
Building a design with those constructs requires a compiler that
supports C++20 coroutines (GCC 10, Clang 5).
The basic idea is to have processes and tasks with delays/event controls
implemented as C++20 coroutines. This allows us to suspend and resume
them at any time.
There are five main runtime classes responsible for managing suspended
coroutines:
* `VlCoroutineHandle`, a wrapper over C++20's `std::coroutine_handle`
with move semantics and automatic cleanup.
* `VlDelayScheduler`, for coroutines suspended by delays. It resumes
them at a proper simulation time.
* `VlTriggerScheduler`, for coroutines suspended by event controls. It
resumes them if its corresponding trigger was set.
* `VlForkSync`, used for syncing `fork..join` and `fork..join_any`
blocks.
* `VlCoroutine`, the return type of all verilated coroutines. It allows
for suspending a stack of coroutines (normally, C++ coroutines are
stackless).
There is a new visitor in `V3Timing.cpp` which:
* scales delays according to the timescale,
* simplifies intra-assignment timing controls and net delays into
regular timing controls and assignments,
* simplifies wait statements into loops with event controls,
* marks processes and tasks with timing controls in them as
suspendable,
* creates delay, trigger scheduler, and fork sync variables,
* transforms timing controls and fork joins into C++ awaits
There are new functions in `V3SchedTiming.cpp` (used by `V3Sched.cpp`)
that integrate static scheduling with timing. This involves providing
external domains for variables, so that the necessary combinational
logic gets triggered after coroutine resumption, as well as statements
that need to be injected into the design eval function to perform this
resumption at the correct time.
There is also a function that transforms forked processes into separate
functions.
See the comments in `verilated_timing.h`, `verilated_timing.cpp`,
`V3Timing.cpp`, and `V3SchedTiming.cpp`, as well as the internals
documentation for more details.
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
2022-08-22 14:26:32 +02:00
|
|
|
of.puts("# Timing enabled? 0/1\n");
|
|
|
|
|
of.puts("VM_TIMING = ");
|
|
|
|
|
of.puts(v3Global.usesTiming() ? "1" : "0");
|
|
|
|
|
of.puts("\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Coverage output mode? 0/1 (from --coverage)\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("VM_COVERAGE = ");
|
|
|
|
|
of.puts(v3Global.opt.coverage() ? "1" : "0");
|
|
|
|
|
of.puts("\n");
|
2020-03-08 14:03:29 +01:00
|
|
|
of.puts("# Parallel builds? 0/1 (from --output-split)\n");
|
|
|
|
|
of.puts("VM_PARALLEL_BUILDS = ");
|
2020-05-25 22:12:34 +02:00
|
|
|
of.puts(v3Global.useParallelBuild() ? "1" : "0");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("\n");
|
2020-04-22 00:49:07 +02:00
|
|
|
of.puts("# Tracing output mode? 0/1 (from --trace/--trace-fst)\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("VM_TRACE = ");
|
|
|
|
|
of.puts(v3Global.opt.trace() ? "1" : "0");
|
|
|
|
|
of.puts("\n");
|
2022-05-20 17:02:43 +02:00
|
|
|
of.puts("# Tracing output mode in VCD format? 0/1 (from --trace)\n");
|
|
|
|
|
of.puts("VM_TRACE_VCD = ");
|
|
|
|
|
of.puts(v3Global.opt.trace() && v3Global.opt.traceFormat().vcd() ? "1" : "0");
|
|
|
|
|
of.puts("\n");
|
2020-10-11 03:17:39 +02:00
|
|
|
of.puts("# Tracing output mode in FST format? 0/1 (from --trace-fst)\n");
|
|
|
|
|
of.puts("VM_TRACE_FST = ");
|
|
|
|
|
of.puts(v3Global.opt.trace() && v3Global.opt.traceFormat().fst() ? "1" : "0");
|
|
|
|
|
of.puts("\n");
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n### Object file lists...\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
for (int support = 0; support < 3; ++support) {
|
2021-07-11 16:42:32 +02:00
|
|
|
for (const bool& slow : {false, true}) {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (support == 2) {
|
|
|
|
|
of.puts("# Global classes, need linked once per executable");
|
|
|
|
|
} else if (support) {
|
|
|
|
|
of.puts("# Generated support classes");
|
|
|
|
|
} else {
|
|
|
|
|
of.puts("# Generated module classes");
|
|
|
|
|
}
|
|
|
|
|
if (slow) {
|
|
|
|
|
of.puts(", non-fast-path, compile with low/medium optimization\n");
|
|
|
|
|
} else {
|
|
|
|
|
of.puts(", fast-path, compile with highest optimization\n");
|
|
|
|
|
}
|
|
|
|
|
of.puts(support == 2 ? "VM_GLOBAL" : support == 1 ? "VM_SUPPORT" : "VM_CLASSES");
|
|
|
|
|
of.puts(slow ? "_SLOW" : "_FAST");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts(" += \\\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
if (support == 2 && v3Global.opt.hierChild()) {
|
|
|
|
|
// Do nothing because VM_GLOBAL is necessary per executable. Top module will
|
|
|
|
|
// have them.
|
|
|
|
|
} else if (support == 2 && !slow) {
|
2019-05-19 22:13:13 +02:00
|
|
|
putMakeClassEntry(of, "verilated.cpp");
|
2021-02-22 03:25:21 +01:00
|
|
|
if (v3Global.dpi()) putMakeClassEntry(of, "verilated_dpi.cpp");
|
|
|
|
|
if (v3Global.opt.vpi()) putMakeClassEntry(of, "verilated_vpi.cpp");
|
|
|
|
|
if (v3Global.opt.savable()) putMakeClassEntry(of, "verilated_save.cpp");
|
|
|
|
|
if (v3Global.opt.coverage()) putMakeClassEntry(of, "verilated_cov.cpp");
|
2019-05-19 22:13:13 +02:00
|
|
|
if (v3Global.opt.trace()) {
|
2020-03-02 03:39:23 +01:00
|
|
|
putMakeClassEntry(of, v3Global.opt.traceSourceBase() + "_c.cpp");
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2022-12-04 23:30:51 +01:00
|
|
|
if (v3Global.usesProbDist()) putMakeClassEntry(of, "verilated_probdist.cpp");
|
Timing support (#3363)
Adds timing support to Verilator. It makes it possible to use delays,
event controls within processes (not just at the start), wait
statements, and forks.
Building a design with those constructs requires a compiler that
supports C++20 coroutines (GCC 10, Clang 5).
The basic idea is to have processes and tasks with delays/event controls
implemented as C++20 coroutines. This allows us to suspend and resume
them at any time.
There are five main runtime classes responsible for managing suspended
coroutines:
* `VlCoroutineHandle`, a wrapper over C++20's `std::coroutine_handle`
with move semantics and automatic cleanup.
* `VlDelayScheduler`, for coroutines suspended by delays. It resumes
them at a proper simulation time.
* `VlTriggerScheduler`, for coroutines suspended by event controls. It
resumes them if its corresponding trigger was set.
* `VlForkSync`, used for syncing `fork..join` and `fork..join_any`
blocks.
* `VlCoroutine`, the return type of all verilated coroutines. It allows
for suspending a stack of coroutines (normally, C++ coroutines are
stackless).
There is a new visitor in `V3Timing.cpp` which:
* scales delays according to the timescale,
* simplifies intra-assignment timing controls and net delays into
regular timing controls and assignments,
* simplifies wait statements into loops with event controls,
* marks processes and tasks with timing controls in them as
suspendable,
* creates delay, trigger scheduler, and fork sync variables,
* transforms timing controls and fork joins into C++ awaits
There are new functions in `V3SchedTiming.cpp` (used by `V3Sched.cpp`)
that integrate static scheduling with timing. This involves providing
external domains for variables, so that the necessary combinational
logic gets triggered after coroutine resumption, as well as statements
that need to be injected into the design eval function to perform this
resumption at the correct time.
There is also a function that transforms forked processes into separate
functions.
See the comments in `verilated_timing.h`, `verilated_timing.cpp`,
`V3Timing.cpp`, and `V3SchedTiming.cpp`, as well as the internals
documentation for more details.
Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
2022-08-22 14:26:32 +02:00
|
|
|
if (v3Global.usesTiming()) putMakeClassEntry(of, "verilated_timing.cpp");
|
2022-07-12 12:41:15 +02:00
|
|
|
if (v3Global.opt.threads()) putMakeClassEntry(of, "verilated_threads.cpp");
|
2022-03-25 20:46:50 +01:00
|
|
|
if (v3Global.opt.usesProfiler()) {
|
|
|
|
|
putMakeClassEntry(of, "verilated_profiler.cpp");
|
|
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
} else if (support == 2 && slow) {
|
|
|
|
|
} else {
|
|
|
|
|
for (AstNodeFile* nodep = v3Global.rootp()->filesp(); nodep;
|
2021-10-22 14:56:48 +02:00
|
|
|
nodep = VN_AS(nodep->nextp(), NodeFile)) {
|
2021-11-13 19:50:44 +01:00
|
|
|
const AstCFile* const cfilep = VN_CAST(nodep, CFile);
|
2020-04-15 13:58:34 +02:00
|
|
|
if (cfilep && cfilep->source() && cfilep->slow() == (slow != 0)
|
|
|
|
|
&& cfilep->support() == (support != 0)) {
|
2019-09-27 09:44:23 +02:00
|
|
|
putMakeClassEntry(of, cfilep->name());
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
of.putsHeader();
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void emitOverallMake() {
|
2019-05-19 22:13:13 +02:00
|
|
|
// Generate the makefile
|
2022-11-20 19:11:01 +01:00
|
|
|
V3OutMkFile of{v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + ".mk"};
|
2019-05-19 22:13:13 +02:00
|
|
|
of.putsHeader();
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("# DESCR"
|
|
|
|
|
"IPTION: Verilator output: "
|
|
|
|
|
"Makefile for building Verilated archive or executable\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("#\n");
|
|
|
|
|
of.puts("# Execute this makefile from the object directory:\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("# make -f " + v3Global.opt.prefix() + ".mk" + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
if (v3Global.opt.exe()) {
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("default: " + v3Global.opt.exeName() + "\n");
|
2021-11-14 15:39:31 +01:00
|
|
|
} else if (!v3Global.opt.libCreate().empty()) {
|
|
|
|
|
of.puts("default: lib" + v3Global.opt.libCreate() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
} else {
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("default: " + v3Global.opt.prefix() + "__ALL.a\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
of.puts("\n### Constants...\n");
|
|
|
|
|
of.puts("# Perl executable (from $PERL)\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("PERL = " + V3Options::getenvPERL() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Path to Verilator kit (from $VERILATOR_ROOT)\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("VERILATOR_ROOT = " + V3Options::getenvVERILATOR_ROOT() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# SystemC include directory with systemc.h (from $SYSTEMC_INCLUDE)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"SYSTEMC_INCLUDE ?= "} + V3Options::getenvSYSTEMC_INCLUDE() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# SystemC library directory with libsystemc.a (from $SYSTEMC_LIBDIR)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"SYSTEMC_LIBDIR ?= "} + V3Options::getenvSYSTEMC_LIBDIR() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
|
2020-05-29 00:51:46 +02:00
|
|
|
// Only check it if we really need the value
|
2021-03-08 03:05:15 +01:00
|
|
|
if (v3Global.opt.systemC() && !V3Options::systemCFound()) {
|
2020-05-29 00:51:46 +02:00
|
|
|
v3fatal("Need $SYSTEMC_INCLUDE in environment or when Verilator configured,\n"
|
|
|
|
|
"and need $SYSTEMC_LIBDIR in environment or when Verilator configured\n"
|
|
|
|
|
"Probably System-C isn't installed, see http://www.systemc.org\n");
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n### Switches...\n");
|
2021-07-08 01:12:52 +02:00
|
|
|
of.puts("# C++ code coverage 0/1 (from --prof-c)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_PROFC = "} + ((v3Global.opt.profC()) ? "1" : "0") + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# SystemC output mode? 0/1 (from --sc)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_SC = "} + ((v3Global.opt.systemC()) ? "1" : "0") + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Legacy or SystemC output mode? 0/1 (from --sc)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_SP_OR_SC = $(VM_SC)\n"});
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Deprecated\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_PCLI = "} + (v3Global.opt.systemC() ? "0" : "1") + "\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts(
|
|
|
|
|
"# Deprecated: SystemC architecture to find link library path (from $SYSTEMC_ARCH)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_SC_TARGET_ARCH = "} + V3Options::getenvSYSTEMC_ARCH() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
|
|
|
|
|
of.puts("\n### Vars...\n");
|
|
|
|
|
of.puts("# Design prefix (from --prefix)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_PREFIX = "} + v3Global.opt.prefix() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Module prefix (from --prefix)\n");
|
2023-04-07 03:00:10 +02:00
|
|
|
of.puts(string{"VM_MODPREFIX = "} + v3Global.opt.modPrefix() + "\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
|
|
|
|
|
of.puts("# User CFLAGS (from -CFLAGS on Verilator command line)\n");
|
|
|
|
|
of.puts("VM_USER_CFLAGS = \\\n");
|
2021-11-14 15:39:31 +01:00
|
|
|
if (!v3Global.opt.libCreate().empty()) of.puts("\t-fPIC \\\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
const V3StringList& cFlags = v3Global.opt.cFlags();
|
2020-08-16 18:54:32 +02:00
|
|
|
for (const string& i : cFlags) of.puts("\t" + i + " \\\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n");
|
|
|
|
|
of.puts("VM_USER_LDLIBS = \\\n");
|
|
|
|
|
const V3StringList& ldLibs = v3Global.opt.ldLibs();
|
2020-08-16 18:54:32 +02:00
|
|
|
for (const string& i : ldLibs) of.puts("\t" + i + " \\\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
V3StringSet dirs;
|
|
|
|
|
of.puts("# User .cpp files (from .cpp's on Verilator command line)\n");
|
|
|
|
|
of.puts("VM_USER_CLASSES = \\\n");
|
|
|
|
|
const V3StringSet& cppFiles = v3Global.opt.cppFiles();
|
2020-08-16 17:43:49 +02:00
|
|
|
for (const auto& cppfile : cppFiles) {
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("\t" + V3Os::filenameNonExt(cppfile) + " \\\n");
|
2021-06-21 00:32:57 +02:00
|
|
|
const string dir = V3Os::filenameDir(cppfile);
|
2020-02-04 05:21:56 +01:00
|
|
|
dirs.insert(dir);
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
of.puts("# User .cpp directories (from .cpp's on Verilator command line)\n");
|
|
|
|
|
of.puts("VM_USER_DIR = \\\n");
|
2020-08-16 17:43:49 +02:00
|
|
|
for (const auto& i : dirs) of.puts("\t" + i + " \\\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
of.puts("\n### Default rules...\n");
|
|
|
|
|
of.puts("# Include list of all generated classes\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts("include " + v3Global.opt.prefix() + "_classes.mk\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
if (v3Global.opt.hierTop()) {
|
|
|
|
|
of.puts("# Include rules for hierarchical blocks\n");
|
|
|
|
|
of.puts("include " + v3Global.opt.prefix() + "_hier.mk\n");
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("# Include global rules\n");
|
|
|
|
|
of.puts("include $(VERILATOR_ROOT)/include/verilated.mk\n");
|
|
|
|
|
|
|
|
|
|
if (v3Global.opt.exe()) {
|
|
|
|
|
of.puts("\n### Executable rules... (from --exe)\n");
|
|
|
|
|
of.puts("VPATH += $(VM_USER_DIR)\n");
|
|
|
|
|
of.puts("\n");
|
2022-11-29 15:02:39 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
|
2022-11-29 15:02:39 +01:00
|
|
|
for (const string& cppfile : cppFiles) {
|
|
|
|
|
const string basename = V3Os::filenameNonExt(cppfile);
|
|
|
|
|
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
|
|
|
|
of.puts(basename + ".o: " + cppfile + "\n");
|
|
|
|
|
of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -c -o $@ $<\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (v3Global.opt.exe()) {
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n### Link rules... (from --exe)\n");
|
2020-04-15 13:58:34 +02:00
|
|
|
of.puts(v3Global.opt.exeName()
|
2020-08-15 15:43:53 +02:00
|
|
|
+ ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS)\n");
|
2020-05-29 00:51:46 +02:00
|
|
|
of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@\n");
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-14 15:39:31 +01:00
|
|
|
if (!v3Global.opt.libCreate().empty()) {
|
2022-04-12 13:04:31 +02:00
|
|
|
const string libCreateDeps = "$(VK_OBJS) $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) "
|
|
|
|
|
+ v3Global.opt.libCreate() + ".o $(VM_HIER_LIBS)";
|
2021-11-14 15:39:31 +01:00
|
|
|
of.puts("\n### Library rules from --lib-create\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
// The rule to create .a is defined in verilated.mk, so just define dependency here.
|
2021-11-14 15:39:31 +01:00
|
|
|
of.puts(v3Global.opt.libCreateName(false) + ": " + libCreateDeps + "\n");
|
2019-10-09 12:47:26 +02:00
|
|
|
of.puts("\n");
|
2020-08-29 13:56:06 +02:00
|
|
|
if (v3Global.opt.hierChild()) {
|
|
|
|
|
// Hierarchical child does not need .so because hierTop() will create .so from .a
|
2021-11-14 15:39:31 +01:00
|
|
|
of.puts("lib" + v3Global.opt.libCreate() + ": " + v3Global.opt.libCreateName(false)
|
|
|
|
|
+ "\n");
|
2020-08-29 13:56:06 +02:00
|
|
|
} else {
|
2021-11-14 15:39:31 +01:00
|
|
|
of.puts(v3Global.opt.libCreateName(true) + ": " + libCreateDeps + "\n");
|
2020-08-29 13:56:06 +02:00
|
|
|
// Linker on mac emits an error if all symbols are not found here,
|
|
|
|
|
// but some symbols that are referred as "DPI-C" can not be found at this moment.
|
|
|
|
|
// So add dynamic_lookup
|
|
|
|
|
of.puts("ifeq ($(shell uname -s),Darwin)\n");
|
|
|
|
|
of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -undefined "
|
2020-08-31 14:22:31 +02:00
|
|
|
"dynamic_lookup -shared -flat_namespace -o $@ $^\n");
|
2020-08-29 13:56:06 +02:00
|
|
|
of.puts("else\n");
|
|
|
|
|
of.puts(
|
|
|
|
|
"\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ $^\n");
|
|
|
|
|
of.puts("endif\n");
|
|
|
|
|
of.puts("\n");
|
2021-11-14 15:39:31 +01:00
|
|
|
of.puts("lib" + v3Global.opt.libCreate() + ": " + v3Global.opt.libCreateName(false)
|
|
|
|
|
+ " " + v3Global.opt.libCreateName(true) + "\n");
|
2020-08-29 13:56:06 +02:00
|
|
|
}
|
2019-10-09 12:47:26 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
of.putsHeader();
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-18 01:44:10 +02:00
|
|
|
explicit EmitMk() {
|
2019-05-19 22:13:13 +02:00
|
|
|
emitClassMake();
|
|
|
|
|
emitOverallMake();
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-11-17 01:56:16 +01:00
|
|
|
virtual ~EmitMk() = default;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-08-15 15:43:53 +02:00
|
|
|
//######################################################################
|
2020-11-19 03:32:16 +01:00
|
|
|
class EmitMkHierVerilation final {
|
2020-08-15 15:43:53 +02:00
|
|
|
const V3HierBlockPlan* const m_planp;
|
|
|
|
|
const string m_makefile; // path of this makefile
|
|
|
|
|
void emitCommonOpts(V3OutMkFile& of) const {
|
|
|
|
|
const string cwd = V3Os::filenameRealPath(".");
|
|
|
|
|
of.puts("# Verilation of hierarchical blocks are executed in this directory\n");
|
|
|
|
|
of.puts("VM_HIER_RUN_DIR := " + cwd + "\n");
|
|
|
|
|
of.puts("# Common options for hierarchical blocks\n");
|
2022-09-18 16:32:43 +02:00
|
|
|
const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.buildDepBin());
|
2021-01-12 04:42:14 +01:00
|
|
|
const string verilator_wrapper = V3Os::filenameDir(fullpath_bin) + "/verilator";
|
|
|
|
|
of.puts("VM_HIER_VERILATOR := " + verilator_wrapper + "\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts("VM_HIER_INPUT_FILES := \\\n");
|
|
|
|
|
const V3StringList& vFiles = v3Global.opt.vFiles();
|
2020-08-16 18:54:32 +02:00
|
|
|
for (const string& i : vFiles) of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
const V3StringSet& libraryFiles = v3Global.opt.libraryFiles();
|
|
|
|
|
of.puts("VM_HIER_VERILOG_LIBS := \\\n");
|
2020-08-16 18:54:32 +02:00
|
|
|
for (const string& i : libraryFiles) {
|
|
|
|
|
of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
}
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
}
|
|
|
|
|
void emitLaunchVerilator(V3OutMkFile& of, const string& argsFile) const {
|
|
|
|
|
of.puts("\t@$(MAKE) -C $(VM_HIER_RUN_DIR) -f " + m_makefile
|
|
|
|
|
+ " hier_launch_verilator \\\n");
|
|
|
|
|
of.puts("\t\tVM_HIER_LAUNCH_VERILATOR_ARGSFILE=\"" + argsFile + "\"\n");
|
|
|
|
|
}
|
|
|
|
|
void emit(V3OutMkFile& of) const {
|
|
|
|
|
of.puts("# Hierarchical Verilation -*- Makefile -*-\n");
|
|
|
|
|
of.puts("# DESCR"
|
2022-12-23 17:32:38 +01:00
|
|
|
"IPTION: Verilator output: Makefile for hierarchical Verilation\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts("#\n");
|
|
|
|
|
of.puts("# The main makefile " + v3Global.opt.prefix() + ".mk calls this makefile\n");
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
of.puts("ifndef VM_HIER_VERILATION_INCLUDED\n");
|
|
|
|
|
of.puts("VM_HIER_VERILATION_INCLUDED = 1\n\n");
|
|
|
|
|
|
|
|
|
|
of.puts(".SUFFIXES:\n");
|
|
|
|
|
of.puts(".PHONY: hier_build hier_verilation hier_launch_verilator\n");
|
|
|
|
|
|
|
|
|
|
of.puts("# Libraries of hierarchical blocks\n");
|
|
|
|
|
of.puts("VM_HIER_LIBS := \\\n");
|
2020-08-31 14:22:31 +02:00
|
|
|
const V3HierBlockPlan::HierVector blocks
|
|
|
|
|
= m_planp->hierBlocksSorted(); // leaf comes first
|
|
|
|
|
// List in order of leaf-last order so that linker can resolve dependency
|
2022-04-18 19:03:56 +02:00
|
|
|
for (auto& block : vlstd::reverse_view(blocks)) {
|
|
|
|
|
of.puts("\t" + block->hierLib(true) + " \\\n");
|
2020-08-15 15:43:53 +02:00
|
|
|
}
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
|
|
|
|
|
// Build hierarchical libraries as soon as possible to get maximum parallelism
|
|
|
|
|
of.puts("hier_build: $(VM_HIER_LIBS) " + v3Global.opt.prefix() + ".mk\n");
|
|
|
|
|
of.puts("\t$(MAKE) -f " + v3Global.opt.prefix() + ".mk\n");
|
|
|
|
|
of.puts("hier_verilation: " + v3Global.opt.prefix() + ".mk\n");
|
|
|
|
|
emitCommonOpts(of);
|
|
|
|
|
|
|
|
|
|
// Instead of direct execute of "cd $(VM_HIER_RUN_DIR) && $(VM_HIER_VERILATOR)",
|
|
|
|
|
// call via make to get message of "Entering directory" and "Leaving directory".
|
|
|
|
|
// This will make some editors and IDEs happy when viewing a logfile.
|
|
|
|
|
of.puts("# VM_HIER_LAUNCH_VERILATOR_ARGSFILE must be passed as a command argument\n");
|
|
|
|
|
of.puts("hier_launch_verilator:\n");
|
|
|
|
|
of.puts("\t$(VM_HIER_VERILATOR) -f $(VM_HIER_LAUNCH_VERILATOR_ARGSFILE)\n");
|
|
|
|
|
|
|
|
|
|
// Top level module
|
|
|
|
|
{
|
|
|
|
|
const string argsFile = v3Global.hierPlanp()->topCommandArgsFileName(false);
|
|
|
|
|
of.puts("\n# Verilate the top module\n");
|
|
|
|
|
of.puts(v3Global.opt.prefix()
|
|
|
|
|
+ ".mk: $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) ");
|
|
|
|
|
of.puts(V3Os::filenameNonDir(argsFile) + " ");
|
2020-11-11 04:10:38 +01:00
|
|
|
for (const auto& itr : *m_planp) of.puts(itr.second->hierWrapper(true) + " ");
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts("\n");
|
|
|
|
|
emitLaunchVerilator(of, argsFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rules to process hierarchical blocks
|
|
|
|
|
of.puts("\n# Verilate hierarchical blocks\n");
|
2022-07-19 12:23:27 +02:00
|
|
|
for (const V3HierBlock* const blockp : m_planp->hierBlocksSorted()) {
|
|
|
|
|
const string prefix = blockp->hierPrefix();
|
|
|
|
|
const string argsFile = blockp->commandArgsFileName(false);
|
|
|
|
|
of.puts(blockp->hierGenerated(true));
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts(": $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) ");
|
|
|
|
|
of.puts(V3Os::filenameNonDir(argsFile) + " ");
|
2022-07-19 12:23:27 +02:00
|
|
|
const V3HierBlock::HierBlockSet& children = blockp->children();
|
2020-08-15 15:43:53 +02:00
|
|
|
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
|
|
|
|
child != children.end(); ++child) {
|
|
|
|
|
of.puts((*child)->hierWrapper(true) + " ");
|
|
|
|
|
}
|
|
|
|
|
of.puts("\n");
|
|
|
|
|
emitLaunchVerilator(of, argsFile);
|
|
|
|
|
|
|
|
|
|
// Rule to build lib*.a
|
2022-07-19 12:23:27 +02:00
|
|
|
of.puts(blockp->hierLib(true));
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts(": ");
|
2022-07-19 12:23:27 +02:00
|
|
|
of.puts(blockp->hierMk(true));
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts(" ");
|
|
|
|
|
for (V3HierBlock::HierBlockSet::const_iterator child = children.begin();
|
|
|
|
|
child != children.end(); ++child) {
|
|
|
|
|
of.puts((*child)->hierLib(true));
|
|
|
|
|
of.puts(" ");
|
|
|
|
|
}
|
2022-07-19 12:23:27 +02:00
|
|
|
of.puts("\n\t$(MAKE) -f " + blockp->hierMk(false) + " -C " + prefix);
|
2020-08-15 15:43:53 +02:00
|
|
|
of.puts(" VM_PREFIX=" + prefix);
|
|
|
|
|
of.puts("\n\n");
|
|
|
|
|
}
|
|
|
|
|
of.puts("endif # Guard\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit EmitMkHierVerilation(const V3HierBlockPlan* planp)
|
2020-08-16 15:55:36 +02:00
|
|
|
: m_planp{planp}
|
|
|
|
|
, m_makefile{v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_hier.mk"} {
|
2022-11-20 19:11:01 +01:00
|
|
|
V3OutMkFile of{m_makefile};
|
2020-08-15 15:43:53 +02:00
|
|
|
emit(of);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Gate class functions
|
|
|
|
|
|
2019-10-18 01:44:10 +02:00
|
|
|
void V3EmitMk::emitmk() {
|
2020-04-15 13:58:34 +02:00
|
|
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
2021-11-26 23:55:36 +01:00
|
|
|
const EmitMk emitter;
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-08-15 15:43:53 +02:00
|
|
|
|
|
|
|
|
void V3EmitMk::emitHierVerilation(const V3HierBlockPlan* planp) {
|
|
|
|
|
UINFO(2, __FUNCTION__ << ": " << endl);
|
2020-12-23 21:21:33 +01:00
|
|
|
EmitMkHierVerilation{planp};
|
2020-08-15 15:43:53 +02:00
|
|
|
}
|