Internals: Move timeunit to pragma, in prep for future parser. No user-functional change intended.

This commit is contained in:
Wilson Snyder 2025-05-06 06:34:49 -04:00
parent 2ed754d5ea
commit da5eb620bf
6 changed files with 49 additions and 33 deletions

View File

@ -336,6 +336,7 @@ public:
NO_INLINE_TASK,
PUBLIC_MODULE,
PUBLIC_TASK,
TIMEUNIT_SET,
UNROLL_DISABLE,
UNROLL_FULL,
FULL_CASE,

View File

@ -1494,18 +1494,24 @@ public:
};
class AstPragma final : public AstNode {
const VPragmaType m_pragType; // Type of pragma
const VTimescale m_timescale; // For TIMEUNIT_SET
public:
// Pragmas don't result in any output code, they're just flags that affect
// other processing in verilator.
AstPragma(FileLine* fl, VPragmaType pragType)
: ASTGEN_SUPER_Pragma(fl)
, m_pragType{pragType} {}
AstPragma(FileLine* fl, VPragmaType pragType, const VTimescale& timescale)
: ASTGEN_SUPER_Pragma(fl)
, m_pragType{pragType}
, m_timescale(timescale) {}
ASTGEN_MEMBERS_AstPragma;
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
bool isPredictOptimizable() const override { return false; }
bool sameNode(const AstNode* samep) const override {
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
}
VTimescale timescale() const { return m_timescale; }
};
class AstPropSpec final : public AstNode {
// A clocked property

View File

@ -88,9 +88,24 @@ void V3LinkLevel::modSortByLevel() {
void V3LinkLevel::timescaling(const ModVec& mods) {
// Timescale determination
const AstNodeModule* modTimedp = nullptr;
VTimescale unit(VTimescale::NONE);
VTimescale unit{VTimescale::NONE};
// Move timeunit attributes from parse to module unit
// Grammar only allows timeunit as module_item, so no need to recurse full tree
for (AstNodeModule* modp : mods) {
for (AstNode *nextp, *childp = modp->stmtsp(); childp; childp = nextp) {
nextp = childp->nextp();
if (AstPragma* pragp = VN_CAST(childp, Pragma)) {
if (pragp->pragType() == VPragmaType::TIMEUNIT_SET) {
modp->timeunit(pragp->timescale());
VL_DO_DANGLING(pragp->unlinkFrBack()->deleteTree(), pragp);
}
}
}
}
// Use highest level module as default unit - already sorted in proper order
for (const auto& modp : mods) {
// Combine timing into later modules
for (AstNodeModule* modp : mods) {
if (!modTimedp && !modp->timeunit().isNone()) {
modTimedp = modp;
unit = modTimedp->timeunit();
@ -106,24 +121,24 @@ void V3LinkLevel::timescaling(const ModVec& mods) {
if (!upkgp->timeunit().isNone()) dunitTimed = true;
}
for (AstNodeModule* nodep : mods) {
if (!v3Global.opt.timeOverrideUnit().isNone()) nodep->timeunit(unit);
if (nodep->timeunit().isNone()) {
for (AstNodeModule* modp : mods) {
if (!v3Global.opt.timeOverrideUnit().isNone()) modp->timeunit(unit);
if (modp->timeunit().isNone()) {
if (modTimedp // Got previous
&& !dunitTimed
&& ( // unit doesn't already include an override
v3Global.opt.timeOverrideUnit().isNone()
&& v3Global.opt.timeDefaultUnit().isNone())
&& nodep->timescaleMatters()) {
nodep->v3warn(TIMESCALEMOD,
"Timescale missing on this module as other modules have "
"it (IEEE 1800-2023 3.14.2.3)\n"
<< nodep->warnContextPrimary() << '\n'
<< modTimedp->warnOther()
<< "... Location of module with timescale\n"
<< modTimedp->warnContextSecondary());
&& modp->timescaleMatters()) {
modp->v3warn(TIMESCALEMOD,
"Timescale missing on this module as other modules have "
"it (IEEE 1800-2023 3.14.2.3)\n"
<< modp->warnContextPrimary() << '\n'
<< modTimedp->warnOther()
<< "... Location of module with timescale\n"
<< modTimedp->warnContextSecondary());
}
nodep->timeunit(unit);
modp->timeunit(unit);
}
}

View File

@ -126,8 +126,8 @@ void V3ParseImp::lexTimescaleParse(FileLine* fl, const char* textp) {
m_timeLastUnit = v3Global.opt.timeComputeUnit(unit);
v3Global.rootp()->timeprecisionMerge(fl, prec);
}
void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
bool precSet, double precVal) {
AstPragma* V3ParseImp::createTimescale(FileLine* fl, bool unitSet, double unitVal, bool precSet,
double precVal) {
VTimescale unit{VTimescale::NONE};
if (unitSet) {
bool bad;
@ -146,16 +146,13 @@ void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, d
fl->v3error("timeprecision illegal value");
}
}
if (!unit.isNone()) {
unit = v3Global.opt.timeComputeUnit(unit);
if (modp) {
modp->timeunit(unit);
} else {
v3Global.rootp()->timeunit(unit);
unitPackage(fl)->timeunit(unit);
}
}
v3Global.rootp()->timeprecisionMerge(fl, prec);
if (unit.isNone()) {
return nullptr;
} else {
unit = v3Global.opt.timeComputeUnit(unit);
return new AstPragma{fl, VPragmaType::TIMEUNIT_SET, unit};
}
}
void V3ParseImp::lexVerilatorCmtLintSave(const FileLine* fl) { m_lexLintState.push_back(*fl); }

View File

@ -181,8 +181,8 @@ public:
void tagNodep(AstNode* nodep) { m_tagNodep = nodep; }
AstNode* tagNodep() const { return m_tagNodep; }
void lexTimescaleParse(FileLine* fl, const char* textp) VL_MT_DISABLED;
void timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
bool precSet, double precVal) VL_MT_DISABLED;
AstPragma* createTimescale(FileLine* fl, bool unitSet, double unitVal, bool precSet,
double precVal) VL_MT_DISABLED;
VTimescale timeLastUnit() const { return m_timeLastUnit; }
void lexFileline(FileLine* fl) { m_lexFileline = fl; }

View File

@ -1227,14 +1227,11 @@ description: // ==IEEE: description
timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
yTIMEUNIT yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), true, $2, false, 0);
$$ = nullptr; }
{ $$ = PARSEP->createTimescale($<fl>2, true, $2, false, 0); }
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), true, $2, true, $4);
$$ = nullptr; }
{ $$ = PARSEP->createTimescale($<fl>2, true, $2, true, $4); }
| yTIMEPRECISION yaTIMENUM ';'
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), false, 0, true, $2);
$$ = nullptr; }
{ $$ = PARSEP->createTimescale($<fl>2, false, 0, true, $2); }
;
//**********************************************************************