Parse setuphold timing check

Signed-off-by: Krzysztof Sychla <ksychla@antmicro.com>
This commit is contained in:
Krzysztof Sychla 2025-02-25 11:16:24 +01:00
parent b4d2f6d2b1
commit ea5da858c2
5 changed files with 70 additions and 2 deletions

View File

@ -134,6 +134,7 @@ Krzysztof Boronski
Krzysztof Boroński
Krzysztof Obłonczek
Krzysztof Starecki
Krzysztof Sychla
Kuba Ober
Larry Doolittle
Liam Braun

View File

@ -3339,6 +3339,24 @@ public:
int instrCount() const override { return INSTR_COUNT_PLI; }
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstSetuphold final : public AstNodeStmt {
// Verilog $setuphold
// @astgen op1 := refevp : AstSenItem
// @astgen op2 := dataevp : AstSenItem
// @astgen op3 := delrefp : Optional[AstSenItem]
// @astgen op4 := deldatap : Optional[AstSenItem]
public:
AstSetuphold(FileLine* fl, AstSenItem* refevp, AstSenItem* dataevp,
AstSenItem* delrefp = nullptr, AstSenItem* deldatap = nullptr)
: ASTGEN_SUPER_Setuphold(fl) {
this->refevp(refevp);
this->dataevp(dataevp);
this->delrefp(delrefp);
this->deldatap(deldatap);
}
ASTGEN_MEMBERS_AstSetuphold;
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstStackTraceT final : public AstNodeStmt {
// $stacktrace used as task
public:

View File

@ -1377,6 +1377,33 @@ class WidthVisitor final : public VNVisitor {
}
}
void visit(AstSetuphold* nodep) override {
FileLine* const flp = nodep->fileline();
AstAssignW* newp = nullptr;
if (nodep->delrefp() != nullptr) {
AstNodeVarRef* lhsp = nodep->delrefp()->varrefp()->cloneTreePure(false);
lhsp->access(VAccess::WRITE);
AstNodeVarRef* rhsp = nodep->refevp()->varrefp()->cloneTreePure(false);
newp = new AstAssignW{flp, lhsp, rhsp};
}
if (nodep->deldatap() != nullptr) {
AstNodeVarRef* lhsp = nodep->deldatap()->varrefp()->cloneTreePure(false);
lhsp->access(VAccess::WRITE);
AstNodeVarRef* rhsp = nodep->dataevp()->varrefp()->cloneTreePure(false);
if (newp == nullptr) {
newp = new AstAssignW{flp, lhsp, rhsp};
} else {
newp->addNextHere(new AstAssignW{flp, lhsp, rhsp});
}
}
nodep->replaceWith(newp);
}
void visit(AstStable* nodep) override {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);

View File

@ -271,7 +271,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$rtoi" { FL; return yD_RTOI; }
"$sampled" { FL; return yD_SAMPLED; }
"$setup" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yaTIMINGSPEC; }
"$setuphold" { FL; return yD_SETUPHOLD; }
"$sformat" { FL; return yD_SFORMAT; }
"$sformatf" { FL; return yD_SFORMATF; }
"$shortrealtobits" { FL; return yD_SHORTREALTOBITS; }

View File

@ -916,6 +916,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yD_ROSE_GCLK "$rose_gclk"
%token<fl> yD_RTOI "$rtoi"
%token<fl> yD_SAMPLED "$sampled"
%token<fl> yD_SETUPHOLD "$setuphold"
%token<fl> yD_SFORMAT "$sformat"
%token<fl> yD_SFORMATF "$sformatf"
%token<fl> yD_SHORTREALTOBITS "$shortrealtobits"
@ -3110,6 +3111,11 @@ minTypMax<nodeExprp>: // IEEE: mintypmax_expression and constant_minty
| delayExpr ':' delayExpr ':' delayExpr { $$ = $3; MINTYPMAXDLYUNSUP($3); DEL($1); DEL($5); }
;
minTypMaxE<nodeExprp>:
/*empty*/ { $$ = nullptr; }
| minTypMax { $$ = $1; }
;
netSigList<varp>: // IEEE: list_of_port_identifiers
netSig { $$ = $1; }
| netSigList ',' netSig { $$ = $1; $1->addNext($3); }
@ -5759,10 +5765,26 @@ tableEntry<udpTableLinep>: // IEEE: combinational_entry + sequential_entry
// Specify
specify_block<nodep>: // ==IEEE: specify_block
ySPECIFY specifyJunkList yENDSPECIFY { $$ = nullptr; }
ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ')' ';' yENDSPECIFY { $$ = nullptr; }
| ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ',' idAnyE ')' ';' yENDSPECIFY { $$ = nullptr; }
| ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ',' idAnyE ',' minTypMaxE ')' ';' yENDSPECIFY { $$ = nullptr; }
| ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ')' ';' yENDSPECIFY { $$ = nullptr; }
| ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' senitemE ')' ';' yENDSPECIFY { $$ = new AstSetuphold{$2, $4, $6, $18}; }
| ySPECIFY yD_SETUPHOLD '(' senitem ',' senitem ',' expr ',' expr ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' senitemE ',' senitemE ')' ';' yENDSPECIFY { $$ = new AstSetuphold{$2, $4, $6, $18, $20}; }
| ySPECIFY yENDSPECIFY { $$ = nullptr; }
;
idAnyE<strp>:
/*empty*/ { $$ = nullptr; }
| idAny { $$ = $1; }
;
senitemE<senItemp>:
/*empty*/ { $$ = nullptr; }
| senitem { $$ = $1; }
;
specifyJunkList:
specifyJunk { } /* ignored */
| specifyJunkList specifyJunk { } /* ignored */