diff --git a/Changes b/Changes index 577bc616a..9258fa6ae 100644 --- a/Changes +++ b/Changes @@ -59,6 +59,7 @@ Verilator 5.029 devel * Fix class reference with pin that is a class reference (#5454). * Fix tracing when name() is empty (#5470). [Sam Shahrestani] * Fix timing mode not exiting on empty events (#5472). +* Fix --binary with .cpp PLI filenames under relative directory paths. Verilator 5.028 2024-08-21 diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 02c7e7b6a..2022aea9b 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -213,9 +213,12 @@ public: const V3StringSet& cppFiles = v3Global.opt.cppFiles(); for (const auto& cppfile : cppFiles) { of.puts("\t" + V3Os::filenameNonDirExt(cppfile) + " \\\n"); - const string dir = V3Os::filenameDir(cppfile); + const string dir + = V3Os::filenameRelativePath(V3Os::filenameDir(cppfile), v3Global.opt.makeDir()); dirs.insert(dir); } + dirs.insert(V3Os::filenameRelativePath(".", v3Global.opt.makeDir())); + of.puts("\n"); of.puts("# User .cpp directories (from .cpp's on Verilator command line)\n"); diff --git a/src/V3Os.cpp b/src/V3Os.cpp index ab0560e51..b11f92e61 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -253,6 +253,55 @@ string V3Os::filenameRealPath(const string& filename) VL_PURE { } } +string V3Os::filenameRelativePath(const string& filename, const string& base) VL_PURE { + const string a = V3Os::filenameRealPath(filename); + const string b = V3Os::filenameRealPath(base); + string result; + if (a == b) return "."; + + auto aIt = a.begin(); + auto bIt = b.begin(); + while (aIt != a.end() && bIt != b.end()) { + // UINFO(9, "fnrp scan " << (aIt - a.begin()) << " " << a.substr(aIt - a.begin()) << endl); + // UINFO(9, "fnrp scan " << (bIt - b.begin()) << " " << b.substr(bIt - b.begin()) << endl); + auto aWordIt = aIt; // position of next slash + for (; aWordIt != a.end(); ++aWordIt) { + if (isSlash(*aWordIt)) break; + } + + auto bWordIt = bIt; // position of next slash + for (; bWordIt != b.end(); ++bWordIt) { + if (isSlash(*bWordIt)) break; + } + + const string aWord = a.substr(aIt - a.begin(), aWordIt - aIt); + const string bWord = b.substr(bIt - b.begin(), bWordIt - bIt); + if (aWord != bWord) break; + aIt = aWordIt; + bIt = bWordIt; + if (aIt != a.end()) ++aIt; // Skip slash + if (bIt != b.end()) ++bIt; // Skip slash + } + + while (bIt != b.end()) { + for (; bIt != b.end(); ++bIt) { + if (isSlash(*bIt)) { + ++bIt; + break; + } + } + if (!result.empty()) result += "/"; + result += ".."; + } + + const string aLeft = a.substr(aIt - a.begin()); + if (!aLeft.empty()) { + if (!result.empty()) result += "/"; + result += aLeft; + } + return filenameCleanup(result); +} + bool V3Os::filenameIsRel(const string& filename) VL_PURE { #if defined(_MSC_VER) return std::filesystem::path(filename).is_relative(); @@ -452,5 +501,19 @@ void V3Os::selfTest() { UASSERT_SELFTEST(string, filenameExt("a.a/b.b/f"), ""); UASSERT_SELFTEST(string, filenameExt("a.a/b.b/f.e"), ".e"); UASSERT_SELFTEST(string, filenameNonDirExt("a.a/b.b/f.e"), "f"); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b", "/a/b"), "."); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b", "/a/b/c"), ".."); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b", "/a/b/c/d"), "../.."); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b/x", "/a/b/c/d"), "../../x"); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b/x/y", "/"), "a/b/x/y"); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b/x/y", "/a/b"), "x/y"); + UASSERT_SELFTEST(string, filenameRelativePath("/a/b/x/y", "/a/q"), "../b/x/y"); + UASSERT_SELFTEST(string, filenameRelativePath("a/b", "a/b"), "."); + UASSERT_SELFTEST(string, filenameRelativePath("a/b", "a/b/c"), ".."); + UASSERT_SELFTEST(string, filenameRelativePath("a/b", "a/b/c/d"), "../.."); + UASSERT_SELFTEST(string, filenameRelativePath("a/b/x", "a/b/c/d"), "../../x"); + UASSERT_SELFTEST(string, filenameRelativePath("a/b/x/y", ""), "a/b/x/y"); + UASSERT_SELFTEST(string, filenameRelativePath("a/b/x/y", "a/b"), "x/y"); + UASSERT_SELFTEST(string, filenameRelativePath("a/b/x/y", "a/q"), "../b/x/y"); #endif } diff --git a/src/V3Os.h b/src/V3Os.h index f0f281be5..5974dc18b 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -55,6 +55,8 @@ public: static string filenameSubstitute(const string& filename); ///< @return realpath of filename static string filenameRealPath(const string& filename) VL_PURE; + ///< @return relative path of filename, relative to base + static string filenameRelativePath(const string& filename, const string& base) VL_PURE; ///< @return filename is relative static bool filenameIsRel(const string& filename) VL_PURE; diff --git a/test_regress/t/t_dpi_binary.py b/test_regress/t/t_dpi_binary.py new file mode 100755 index 000000000..1663c1d56 --- /dev/null +++ b/test_regress/t/t_dpi_binary.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.pli_filename = "t/t_dpi_binary_c.cpp" + +test.compile(v_flags2=[test.pli_filename], verilator_flags2=['--binary']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_dpi_binary.v b/test_regress/t/t_dpi_binary.v new file mode 100644 index 000000000..320ba11f4 --- /dev/null +++ b/test_regress/t/t_dpi_binary.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2009 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 + +module t (); + + initial begin + // All Finished is in dpic_final + $finish; + end + + import "DPI-C" context function void dpic_final(); + final dpic_final(); + +endmodule diff --git a/test_regress/t/t_dpi_binary_c.cpp b/test_regress/t/t_dpi_binary_c.cpp new file mode 100644 index 000000000..ffe6049d1 --- /dev/null +++ b/test_regress/t/t_dpi_binary_c.cpp @@ -0,0 +1,25 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2009 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 "t_dpi_binary_c.h" + +#include "svdpi.h" + +#include + +//====================================================================== + +extern "C" void dpic_final(); + +void dpic_final() { + printf("%s:\n", __func__); + printf("*-* All Finished *-*\n"); +} diff --git a/test_regress/t/t_dpi_binary_c.h b/test_regress/t/t_dpi_binary_c.h new file mode 100644 index 000000000..d15da366a --- /dev/null +++ b/test_regress/t/t_dpi_binary_c.h @@ -0,0 +1,12 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2009 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 +// +//************************************************************************* + +// Empty file just to check that GCC finds it properly