Support $setuphold (#5884)

This commit is contained in:
Krzysztof Sychla
2025-04-02 06:08:51 -04:00
committed by GitHub
parent 0b9c2163d5
commit cd5997a2e6
8 changed files with 239 additions and 14 deletions
+18
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 : AstNodeExpr
// @astgen op2 := dataevp : AstNodeExpr
// @astgen op3 := delrefp : Optional[AstNodeExpr]
// @astgen op4 := deldatap : Optional[AstNodeExpr]
public:
AstSetuphold(FileLine* fl, AstNodeExpr* refevp, AstNodeExpr* dataevp,
AstNodeExpr* delrefp = nullptr, AstNodeExpr* 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:
+40
View File
@@ -1377,6 +1377,46 @@ class WidthVisitor final : public VNVisitor {
}
}
void visit(AstSetuphold* nodep) override {
FileLine* const flp = nodep->fileline();
AstAssignW* newp = nullptr;
if (nodep->delrefp()) {
newp = convertSetupholdToAssign(flp, nodep->refevp(), nodep->delrefp());
}
if (nodep->deldatap()) {
if (!newp) {
newp = convertSetupholdToAssign(flp, nodep->dataevp(), nodep->deldatap());
} else {
newp->addNextHere(
convertSetupholdToAssign(flp, nodep->dataevp(), nodep->deldatap()));
}
}
if (!newp) {
pushDeletep(nodep->unlinkFrBack());
return;
}
nodep->replaceWith(newp);
}
AstAssignW* convertSetupholdToAssign(FileLine* const flp, AstNodeExpr* const evp,
AstNodeExpr* const delp) {
AstNodeExpr* const lhsp = delp->cloneTreePure(false);
AstNodeExpr* const rhsp = evp->cloneTreePure(false);
UASSERT_OBJ(VN_IS(lhsp, NodeVarRef) || VN_IS(lhsp, NodePreSel), lhsp,
"Incorrect reference in a timing check");
if (AstNodeVarRef* varRefp = VN_CAST(lhsp, NodeVarRef)) {
if (varRefp->varp()->direction() == VDirection::INPUT) { return nullptr; }
varRefp->access(VAccess::WRITE);
}
if (AstNodePreSel* selp = VN_CAST(lhsp, NodePreSel)) {
if (AstNodeVarRef* varRefp = VN_CAST(selp->fromp(), NodeVarRef)) {
if (varRefp->varp()->direction() == VDirection::INPUT) { return nullptr; }
varRefp->access(VAccess::WRITE);
}
}
return new AstAssignW{flp, lhsp, rhsp};
}
void visit(AstStable* nodep) override {
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
+10 -2
View File
@@ -79,7 +79,7 @@ static double lexParseDouble(FileLine* fl, const char* textp, size_t length) {
%o 25000
%s V95 V01NC V01C V05 S05 S09 S12 S17 S23
%s ATTRMODE QQQ STRING TABLE
%s ATTRMODE QQQ STRING TABLE EDGEDESC
%s VA5 SAX VLT
%s SYSCHDR SYSCHDRP SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
@@ -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; }
@@ -328,6 +328,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"default" { FL; return yDEFAULT; }
"defparam" { FL; return yDEFPARAM; }
"disable" { FL; return yDISABLE; }
"edge"/{ws}*"[" { FL; yy_push_state(EDGEDESC); return yEDGE; }
"edge" { FL; return yEDGE; }
"else" { FL; return yELSE; }
"end" { FL; return yEND; }
@@ -1023,6 +1024,13 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<TABLE><<EOF>> { FL; yylval.fl->v3error("EOF in 'table'");
yyleng = 0; yy_pop_state(); FL_BRK; yyterminate(); }
<EDGEDESC>{
01|10|[01][zZxX]|[zZxX][01] { FL; return yaEDGEDESC; }
}
<EDGEDESC>","|"[" { FL; return yytext[0]; }
<EDGEDESC>{ws} { FL_FWD; FL_BRK; } /* otherwise ignore white-space */
<EDGEDESC>"]" { FL; yy_pop_state(); return yytext[0]; }
/************************************************************************/
/* Preprocessor */
/* Common for all SYSC header states */
+68 -11
View File
@@ -443,6 +443,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
// IEEE: string_literal
%token<strp> yaSTRING "STRING"
%token<strp> yaSTRING__IGNORE "STRING-ignored" // Used when expr:string not allowed
// IEEE: edge_descriptor
%token<nump> yaEDGEDESC "EDGE DESCRIPTOR"
%token<fl> yaTIMINGSPEC "TIMING SPEC ELEMENT"
@@ -917,6 +919,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"
@@ -3117,6 +3120,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); }
@@ -5765,33 +5773,82 @@ tableEntry<udpTableLinep>: // IEEE: combinational_entry + sequential_entry
//************************************************
// Specify
specify_block<nodep>: // ==IEEE: specify_block
ySPECIFY specifyJunkList yENDSPECIFY { $$ = nullptr; }
specify_block<nodep>: // ==IEEE: specify_block
ySPECIFY specify_itemList yENDSPECIFY { $$ = $2; }
| ySPECIFY yENDSPECIFY { $$ = nullptr; }
;
specifyJunkList:
specifyJunk { } /* ignored */
| specifyJunkList specifyJunk { } /* ignored */
specify_itemList<nodep>: // IEEE: { specify_item }
specify_item { $$ = $1; }
| specify_itemList specify_item { $$ = addNextNull($1, $2); }
;
specifyJunk:
BISONPRE_NOT(ySPECIFY,yENDSPECIFY) { }
| ySPECIFY specifyJunk yENDSPECIFY { }
| error {}
specify_item<nodep>: // ==IEEE: specify_item
system_timing_check { $$ = $1; }
| junkToSemiList ';' { $$ = nullptr; }
;
specparam_declaration<nodep>: // ==IEEE: specparam_declaration
specparam_declaration<nodep>: // ==IEEE: specparam_declaration
ySPECPARAM junkToSemiList ';' { $$ = nullptr; }
;
system_timing_check<nodep>: // ==IEEE: system_timing_check
setuphold_timing_check { $$ = $1; }
;
setuphold_timing_check<nodep>: // ==IEEE: $setuphold_timing_check
yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ')' ';' { $$ = nullptr; }
| yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ',' idAnyE ')' ';' { $$ = nullptr; }
| yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ',' idAnyE ',' minTypMaxE ')' ';' { $$ = nullptr; }
| yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ',' idAnyE ',' minTypMaxE ',' minTypMaxE ')' ';' { $$ = nullptr; }
| yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' delayed_referenceE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17}; }
| yD_SETUPHOLD '(' timing_check_event ',' timing_check_event ',' timing_check_limit ',' timing_check_limit ',' idAnyE ',' minTypMaxE ',' minTypMaxE ',' delayed_referenceE ',' delayed_referenceE ')' ';' { $$ = new AstSetuphold{$1, $3, $5, $17, $19}; }
;
timing_check_event<nodeExprp>: // ==IEEE: $timing_check_event
terminal_identifier { $$ = $1; }
| yPOSEDGE terminal_identifier { $$ = $2; }
| yNEGEDGE terminal_identifier { $$ = $2; }
| yEDGE terminal_identifier { $$ = $2; }
| yEDGE '[' edge_descriptor_list ']' terminal_identifier { $$ = $5; }
| terminal_identifier yP_ANDANDAND expr { $$ = $1; }
| yPOSEDGE terminal_identifier yP_ANDANDAND expr { $$ = $2; }
| yNEGEDGE terminal_identifier yP_ANDANDAND expr { $$ = $2; }
| yEDGE terminal_identifier yP_ANDANDAND expr { $$ = $2; }
| yEDGE '[' edge_descriptor_list ']' terminal_identifier yP_ANDANDAND expr { $$ = $5; }
;
edge_descriptor_list:
yaEDGEDESC { }
| edge_descriptor_list ',' yaEDGEDESC { }
;
timing_check_limit<nodeExprp>:
expr { $$ = $1; }
| expr ':' expr ':' expr { $$ = $3; }
;
delayed_referenceE<nodeExprp>:
/*empty*/ { $$ = nullptr; }
| terminal_identifier { $$ = $1; }
;
terminal_identifier<nodeExprp>:
idArrayed { $$ = $1; }
;
idAnyE<strp>:
/*empty*/ { $$ = nullptr; }
| idAny { $$ = $1; }
;
junkToSemiList:
junkToSemi { } /* ignored */
| junkToSemiList junkToSemi { } /* ignored */
;
junkToSemi:
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE) { }
BISONPRE_NOT(';',yENDSPECIFY,yENDMODULE,yD_SETUPHOLD) { }
| error {}
;