Internals: Move timeunit to pragma, in prep for future parser. No user-functional change intended.
This commit is contained in:
parent
2ed754d5ea
commit
da5eb620bf
|
|
@ -336,6 +336,7 @@ public:
|
||||||
NO_INLINE_TASK,
|
NO_INLINE_TASK,
|
||||||
PUBLIC_MODULE,
|
PUBLIC_MODULE,
|
||||||
PUBLIC_TASK,
|
PUBLIC_TASK,
|
||||||
|
TIMEUNIT_SET,
|
||||||
UNROLL_DISABLE,
|
UNROLL_DISABLE,
|
||||||
UNROLL_FULL,
|
UNROLL_FULL,
|
||||||
FULL_CASE,
|
FULL_CASE,
|
||||||
|
|
|
||||||
|
|
@ -1494,18 +1494,24 @@ public:
|
||||||
};
|
};
|
||||||
class AstPragma final : public AstNode {
|
class AstPragma final : public AstNode {
|
||||||
const VPragmaType m_pragType; // Type of pragma
|
const VPragmaType m_pragType; // Type of pragma
|
||||||
|
const VTimescale m_timescale; // For TIMEUNIT_SET
|
||||||
public:
|
public:
|
||||||
// Pragmas don't result in any output code, they're just flags that affect
|
// Pragmas don't result in any output code, they're just flags that affect
|
||||||
// other processing in verilator.
|
// other processing in verilator.
|
||||||
AstPragma(FileLine* fl, VPragmaType pragType)
|
AstPragma(FileLine* fl, VPragmaType pragType)
|
||||||
: ASTGEN_SUPER_Pragma(fl)
|
: ASTGEN_SUPER_Pragma(fl)
|
||||||
, m_pragType{pragType} {}
|
, m_pragType{pragType} {}
|
||||||
|
AstPragma(FileLine* fl, VPragmaType pragType, const VTimescale& timescale)
|
||||||
|
: ASTGEN_SUPER_Pragma(fl)
|
||||||
|
, m_pragType{pragType}
|
||||||
|
, m_timescale(timescale) {}
|
||||||
ASTGEN_MEMBERS_AstPragma;
|
ASTGEN_MEMBERS_AstPragma;
|
||||||
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
|
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
|
||||||
bool isPredictOptimizable() const override { return false; }
|
bool isPredictOptimizable() const override { return false; }
|
||||||
bool sameNode(const AstNode* samep) const override {
|
bool sameNode(const AstNode* samep) const override {
|
||||||
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
|
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
|
||||||
}
|
}
|
||||||
|
VTimescale timescale() const { return m_timescale; }
|
||||||
};
|
};
|
||||||
class AstPropSpec final : public AstNode {
|
class AstPropSpec final : public AstNode {
|
||||||
// A clocked property
|
// A clocked property
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,24 @@ void V3LinkLevel::modSortByLevel() {
|
||||||
void V3LinkLevel::timescaling(const ModVec& mods) {
|
void V3LinkLevel::timescaling(const ModVec& mods) {
|
||||||
// Timescale determination
|
// Timescale determination
|
||||||
const AstNodeModule* modTimedp = nullptr;
|
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
|
// 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()) {
|
if (!modTimedp && !modp->timeunit().isNone()) {
|
||||||
modTimedp = modp;
|
modTimedp = modp;
|
||||||
unit = modTimedp->timeunit();
|
unit = modTimedp->timeunit();
|
||||||
|
|
@ -106,24 +121,24 @@ void V3LinkLevel::timescaling(const ModVec& mods) {
|
||||||
if (!upkgp->timeunit().isNone()) dunitTimed = true;
|
if (!upkgp->timeunit().isNone()) dunitTimed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AstNodeModule* nodep : mods) {
|
for (AstNodeModule* modp : mods) {
|
||||||
if (!v3Global.opt.timeOverrideUnit().isNone()) nodep->timeunit(unit);
|
if (!v3Global.opt.timeOverrideUnit().isNone()) modp->timeunit(unit);
|
||||||
if (nodep->timeunit().isNone()) {
|
if (modp->timeunit().isNone()) {
|
||||||
if (modTimedp // Got previous
|
if (modTimedp // Got previous
|
||||||
&& !dunitTimed
|
&& !dunitTimed
|
||||||
&& ( // unit doesn't already include an override
|
&& ( // unit doesn't already include an override
|
||||||
v3Global.opt.timeOverrideUnit().isNone()
|
v3Global.opt.timeOverrideUnit().isNone()
|
||||||
&& v3Global.opt.timeDefaultUnit().isNone())
|
&& v3Global.opt.timeDefaultUnit().isNone())
|
||||||
&& nodep->timescaleMatters()) {
|
&& modp->timescaleMatters()) {
|
||||||
nodep->v3warn(TIMESCALEMOD,
|
modp->v3warn(TIMESCALEMOD,
|
||||||
"Timescale missing on this module as other modules have "
|
"Timescale missing on this module as other modules have "
|
||||||
"it (IEEE 1800-2023 3.14.2.3)\n"
|
"it (IEEE 1800-2023 3.14.2.3)\n"
|
||||||
<< nodep->warnContextPrimary() << '\n'
|
<< modp->warnContextPrimary() << '\n'
|
||||||
<< modTimedp->warnOther()
|
<< modTimedp->warnOther()
|
||||||
<< "... Location of module with timescale\n"
|
<< "... Location of module with timescale\n"
|
||||||
<< modTimedp->warnContextSecondary());
|
<< modTimedp->warnContextSecondary());
|
||||||
}
|
}
|
||||||
nodep->timeunit(unit);
|
modp->timeunit(unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,8 +126,8 @@ void V3ParseImp::lexTimescaleParse(FileLine* fl, const char* textp) {
|
||||||
m_timeLastUnit = v3Global.opt.timeComputeUnit(unit);
|
m_timeLastUnit = v3Global.opt.timeComputeUnit(unit);
|
||||||
v3Global.rootp()->timeprecisionMerge(fl, prec);
|
v3Global.rootp()->timeprecisionMerge(fl, prec);
|
||||||
}
|
}
|
||||||
void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
|
AstPragma* V3ParseImp::createTimescale(FileLine* fl, bool unitSet, double unitVal, bool precSet,
|
||||||
bool precSet, double precVal) {
|
double precVal) {
|
||||||
VTimescale unit{VTimescale::NONE};
|
VTimescale unit{VTimescale::NONE};
|
||||||
if (unitSet) {
|
if (unitSet) {
|
||||||
bool bad;
|
bool bad;
|
||||||
|
|
@ -146,16 +146,13 @@ void V3ParseImp::timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, d
|
||||||
fl->v3error("timeprecision illegal value");
|
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);
|
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); }
|
void V3ParseImp::lexVerilatorCmtLintSave(const FileLine* fl) { m_lexLintState.push_back(*fl); }
|
||||||
|
|
|
||||||
|
|
@ -181,8 +181,8 @@ public:
|
||||||
void tagNodep(AstNode* nodep) { m_tagNodep = nodep; }
|
void tagNodep(AstNode* nodep) { m_tagNodep = nodep; }
|
||||||
AstNode* tagNodep() const { return m_tagNodep; }
|
AstNode* tagNodep() const { return m_tagNodep; }
|
||||||
void lexTimescaleParse(FileLine* fl, const char* textp) VL_MT_DISABLED;
|
void lexTimescaleParse(FileLine* fl, const char* textp) VL_MT_DISABLED;
|
||||||
void timescaleMod(FileLine* fl, AstNodeModule* modp, bool unitSet, double unitVal,
|
AstPragma* createTimescale(FileLine* fl, bool unitSet, double unitVal, bool precSet,
|
||||||
bool precSet, double precVal) VL_MT_DISABLED;
|
double precVal) VL_MT_DISABLED;
|
||||||
VTimescale timeLastUnit() const { return m_timeLastUnit; }
|
VTimescale timeLastUnit() const { return m_timeLastUnit; }
|
||||||
|
|
||||||
void lexFileline(FileLine* fl) { m_lexFileline = fl; }
|
void lexFileline(FileLine* fl) { m_lexFileline = fl; }
|
||||||
|
|
|
||||||
|
|
@ -1227,14 +1227,11 @@ description: // ==IEEE: description
|
||||||
|
|
||||||
timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
|
timeunits_declaration<nodep>: // ==IEEE: timeunits_declaration
|
||||||
yTIMEUNIT yaTIMENUM ';'
|
yTIMEUNIT yaTIMENUM ';'
|
||||||
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), true, $2, false, 0);
|
{ $$ = PARSEP->createTimescale($<fl>2, true, $2, false, 0); }
|
||||||
$$ = nullptr; }
|
|
||||||
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';'
|
| yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';'
|
||||||
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), true, $2, true, $4);
|
{ $$ = PARSEP->createTimescale($<fl>2, true, $2, true, $4); }
|
||||||
$$ = nullptr; }
|
|
||||||
| yTIMEPRECISION yaTIMENUM ';'
|
| yTIMEPRECISION yaTIMENUM ';'
|
||||||
{ PARSEP->timescaleMod($<fl>2, SYMP->findTopNodeModule($<fl>1, false), false, 0, true, $2);
|
{ $$ = PARSEP->createTimescale($<fl>2, false, 0, true, $2); }
|
||||||
$$ = nullptr; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
//**********************************************************************
|
//**********************************************************************
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue