From 6bad0e14ce76238a4f05b67d0d536fb978e8ee8f Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 29 Jul 2021 08:40:41 -0400 Subject: [PATCH] Support timeunit/timeprecision in $unit. --- Changes | 1 + src/V3LinkLevel.cpp | 6 ++++++ src/V3ParseImp.cpp | 6 ++++-- src/V3ParseImp.h | 12 ++++++++++++ src/verilog.y | 20 ++++--------------- test_regress/t/t_timescale_unit.out | 4 ++++ test_regress/t/t_timescale_unit.pl | 23 ++++++++++++++++++++++ test_regress/t/t_timescale_unit.v | 30 +++++++++++++++++++++++++++++ 8 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 test_regress/t/t_timescale_unit.out create mode 100755 test_regress/t/t_timescale_unit.pl create mode 100644 test_regress/t/t_timescale_unit.v diff --git a/Changes b/Changes index a839034b2..158ecf997 100644 --- a/Changes +++ b/Changes @@ -14,6 +14,7 @@ Verilator 4.211 devel **Minor:** * Support unpacked array localparams in tasks/functions (#3078). [Geza Lore] +* Support timeunit/timeprecision in $unit. * Add --instr-count-dpi to tune assumed DPI import cost for multithreaded model scheduling. Default value changed to 200 (#3068). [Yinan Xu] * Output files are split based on the set of headers required diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 728073fc5..d83627ef3 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -100,10 +100,16 @@ void V3LinkLevel::timescaling(const ModVec& mods) { if (unit.isNone()) unit = VTimescale(VTimescale::TS_DEFAULT); v3Global.rootp()->timeunit(unit); + bool dunitTimed = false; // $unit had a timeunit + if (const AstPackage* const upkgp = v3Global.rootp()->dollarUnitPkgp()) { + if (!upkgp->timeunit().isNone()) dunitTimed = true; + } + for (AstNodeModule* nodep : mods) { if (!v3Global.opt.timeOverrideUnit().isNone()) nodep->timeunit(unit); if (nodep->timeunit().isNone()) { if (modTimedp // Got previous + && !dunitTimed && ( // unit doesn't already include an override v3Global.opt.timeOverrideUnit().isNone() && v3Global.opt.timeDefaultUnit().isNone()) diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 9a6272e45..f1c042aa8 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -108,10 +108,12 @@ void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, d } } if (!unit.isNone()) { + unit = v3Global.opt.timeComputeUnit(unit); if (modp) { - modp->timeunit(v3Global.opt.timeComputeUnit(unit)); + modp->timeunit(unit); } else { - fl->v3error("timeunit/timeprecision not under a module"); + v3Global.rootp()->timeunit(unit); + unitPackage(fl)->timeunit(unit); } } v3Global.rootp()->timeprecisionMerge(fl, prec); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index a9477921c..fd6422dce 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -301,6 +301,18 @@ public: //==== Symbol tables V3ParseSym* symp() { return m_symp; } + AstPackage* unitPackage(FileLine* fl) { + // Find one made earlier? + VSymEnt* const rootSymp = symp()->symRootp()->findIdFlat(AstPackage::dollarUnitName()); + AstPackage* pkgp; + if (!rootSymp) { + pkgp = parsep()->rootp()->dollarUnitPkgAddp(); + symp()->reinsert(pkgp, symp()->symRootp()); // Don't push/pop scope as they're global + } else { + pkgp = VN_CAST(rootSymp->nodep(), Package); + } + return pkgp; + } public: // CONSTRUCTORS diff --git a/src/verilog.y b/src/verilog.y index 8ce6e77b7..21015f440 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -148,18 +148,6 @@ public: m_pinNum = m_pinStack.top(); m_pinStack.pop(); } - AstPackage* unitPackage(FileLine* fl) { - // Find one made earlier? - VSymEnt* symp = SYMP->symRootp()->findIdFlat(AstPackage::dollarUnitName()); - AstPackage* pkgp; - if (!symp) { - pkgp = PARSEP->rootp()->dollarUnitPkgAddp(); - SYMP->reinsert(pkgp, SYMP->symRootp()); // Don't push/pop scope as they're global - } else { - pkgp = VN_CAST(symp->nodep(), Package); - } - return pkgp; - } AstNodeDType* addRange(AstBasicDType* dtypep, AstNodeRange* rangesp, bool isPacked) { // If dtypep isn't basic, don't use this, call createArray() instead if (!rangesp) { @@ -1043,8 +1031,8 @@ description: // ==IEEE: description | interface_declaration { } | program_declaration { } | package_declaration { } - | package_item { if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); } - | bind_directive { if ($1) GRAMMARP->unitPackage($1->fileline())->addStmtp($1); } + | package_item { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); } + | bind_directive { if ($1) PARSEP->unitPackage($1->fileline())->addStmtp($1); } // unsupported // IEEE: config_declaration // // Verilator only | yaT_RESETALL { } // Else, under design, and illegal based on IEEE 22.3 @@ -6157,7 +6145,7 @@ dollarUnitNextId: // $unit // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yD_UNIT - { $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($1), nullptr); + { $$ = new AstClassOrPackageRef{$1, "$unit", PARSEP->unitPackage($1), nullptr}; SYMP->nextId(PARSEP->rootp()); } ; @@ -6166,7 +6154,7 @@ localNextId: // local // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yLOCAL__COLONCOLON - { $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($1), nullptr); + { $$ = new AstClassOrPackageRef{$1, "local::", PARSEP->unitPackage($1), nullptr}; SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; diff --git a/test_regress/t/t_timescale_unit.out b/test_regress/t/t_timescale_unit.out new file mode 100644 index 000000000..6f3bba3f0 --- /dev/null +++ b/test_regress/t/t_timescale_unit.out @@ -0,0 +1,4 @@ +Time scale of __024unit is 10ps / 10ps +Time scale of from_unit is 10ps / 10ps +Time scale of t is 100ps / 10ps +*-* All Finished *-* diff --git a/test_regress/t/t_timescale_unit.pl b/test_regress/t/t_timescale_unit.pl new file mode 100755 index 000000000..88b7809fc --- /dev/null +++ b/test_regress/t/t_timescale_unit.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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( + ); + +execute( + check_finished => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); + +1; diff --git a/test_regress/t/t_timescale_unit.v b/test_regress/t/t_timescale_unit.v new file mode 100644 index 000000000..71825185c --- /dev/null +++ b/test_regress/t/t_timescale_unit.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under The Creative Commons Public Domain, for +// any use, without warranty, 2021 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +timeunit 10ps; +timeprecision 10ps; + +task show; + $printtimescale; +endtask + +module from_unit; + task show; + $printtimescale; + endtask +endmodule + +module t; + from_unit from_unit(); + timeunit 100ps; + initial begin + show(); + from_unit.show(); + $printtimescale; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule