Support `$past_gclk`
This commit is contained in:
parent
7a3f1f16ca
commit
73ca2ab997
|
@ -460,7 +460,7 @@ private:
|
|||
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
||||
AstSenTree* sentreep = nodep->sentreep();
|
||||
if (sentreep) sentreep->unlinkFrBack();
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd{fl, past, new AstNot{fl, exprp->cloneTreePure(false)}};
|
||||
exprp->dtypeSetBit();
|
||||
|
@ -481,7 +481,7 @@ private:
|
|||
if (exprp->width() > 1) exprp = new AstSel{fl, exprp, 0, 1};
|
||||
AstSenTree* sentreep = nodep->sentreep();
|
||||
if (sentreep) sentreep->unlinkFrBack();
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstAnd{fl, new AstNot{fl, past}, exprp->cloneTreePure(false)};
|
||||
exprp->dtypeSetBit();
|
||||
|
@ -496,7 +496,7 @@ private:
|
|||
AstNodeExpr* exprp = nodep->exprp()->unlinkFrBack();
|
||||
AstSenTree* sentreep = nodep->sentreep();
|
||||
if (sentreep) sentreep->unlinkFrBack();
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp, nullptr};
|
||||
AstNodeExpr* const past = new AstPast{fl, exprp};
|
||||
past->dtypeFrom(exprp);
|
||||
exprp = new AstEq{fl, past, exprp->cloneTreePure(false)};
|
||||
exprp->dtypeSetBit();
|
||||
|
@ -514,7 +514,7 @@ private:
|
|||
|
||||
if (m_disablep) lhsp = new AstAnd{fl, new AstNot{fl, m_disablep}, lhsp};
|
||||
|
||||
AstNodeExpr* const past = new AstPast{fl, lhsp, nullptr};
|
||||
AstNodeExpr* const past = new AstPast{fl, lhsp};
|
||||
past->dtypeFrom(lhsp);
|
||||
AstNodeExpr* const exprp = new AstOr{fl, new AstNot{fl, past}, rhsp};
|
||||
exprp->dtypeSetBit();
|
||||
|
|
|
@ -1732,10 +1732,12 @@ class AstPast final : public AstNodeExpr {
|
|||
// @astgen op2 := ticksp : Optional[AstNode]
|
||||
// @astgen op3 := sentreep : Optional[AstSenTree]
|
||||
public:
|
||||
AstPast(FileLine* fl, AstNodeExpr* exprp, AstNode* ticksp)
|
||||
AstPast(FileLine* fl, AstNodeExpr* exprp, AstNode* ticksp = nullptr,
|
||||
AstSenTree* sentreep = nullptr)
|
||||
: ASTGEN_SUPER_Past(fl) {
|
||||
this->exprp(exprp);
|
||||
this->ticksp(ticksp);
|
||||
this->sentreep(sentreep);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstPast;
|
||||
string emitVerilog() override { V3ERROR_NA_RETURN(""); }
|
||||
|
|
|
@ -395,9 +395,13 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
|||
void visit(AstPast* nodep) override {
|
||||
putfs(nodep, "$past(");
|
||||
iterateAndNextConstNull(nodep->exprp());
|
||||
if (nodep->ticksp()) {
|
||||
if (nodep->ticksp() || nodep->sentreep()) {
|
||||
puts(", ");
|
||||
iterateAndNextConstNull(nodep->ticksp());
|
||||
if (nodep->sentreep()) {
|
||||
puts(", ");
|
||||
iterateAndNextConstNull(nodep->sentreep());
|
||||
}
|
||||
}
|
||||
puts(")");
|
||||
}
|
||||
|
|
|
@ -1356,6 +1356,7 @@ class WidthVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
userIterate(nodep->sentreep(), nullptr);
|
||||
}
|
||||
}
|
||||
void visit(AstRose* nodep) override {
|
||||
|
|
|
@ -488,6 +488,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
|
|||
"$onehot" { FL; return yD_ONEHOT; }
|
||||
"$onehot0" { FL; return yD_ONEHOT0; }
|
||||
"$past" { FL; return yD_PAST; }
|
||||
"$past_gclk" { FL; return yD_PAST_GCLK; }
|
||||
"$right" { FL; return yD_RIGHT; }
|
||||
"$root" { FL; return yD_ROOT; }
|
||||
"$rose" { FL; return yD_ROSE; }
|
||||
|
|
|
@ -911,6 +911,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
|
|||
%token<fl> yD_ONEHOT "$onehot"
|
||||
%token<fl> yD_ONEHOT0 "$onehot0"
|
||||
%token<fl> yD_PAST "$past"
|
||||
%token<fl> yD_PAST_GCLK "$past_gclk"
|
||||
%token<fl> yD_POW "$pow"
|
||||
%token<fl> yD_PRINTTIMESCALE "$printtimescale"
|
||||
%token<fl> yD_RANDOM "$random"
|
||||
|
@ -4491,7 +4492,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_LOW '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_LOW, $3, $5}; }
|
||||
| yD_ONEHOT '(' expr ')' { $$ = new AstOneHot{$1, $3}; }
|
||||
| yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0{$1, $3}; }
|
||||
| yD_PAST '(' expr ')' { $$ = new AstPast{$1, $3, nullptr}; }
|
||||
| yD_PAST '(' expr ')' { $$ = new AstPast{$1, $3}; }
|
||||
| yD_PAST '(' expr ',' exprE ')' { $$ = new AstPast{$1, $3, $5}; }
|
||||
| yD_PAST '(' expr ',' exprE ',' exprE ')'
|
||||
{ if ($7) BBUNSUP($1, "Unsupported: $past expr2 and/or clock arguments");
|
||||
|
@ -4499,6 +4500,7 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
|
|||
| yD_PAST '(' expr ',' exprE ',' exprE ',' clocking_eventE ')'
|
||||
{ if ($7 || $9) BBUNSUP($1, "Unsupported: $past expr2 and/or clock arguments");
|
||||
$$ = new AstPast{$1, $3, $5}; }
|
||||
| yD_PAST_GCLK '(' expr ')' { $$ = new AstPast{$1, $3, nullptr, GRAMMARP->createGlobalClockSenTree($1)}; }
|
||||
| yD_POW '(' expr ',' expr ')' { $$ = new AstPowD{$1, $3, $5}; }
|
||||
| yD_RANDOM '(' expr ')' { $$ = new AstRand{$1, $3, false}; }
|
||||
| yD_RANDOM parenE { $$ = new AstRand{$1, nullptr, false}; }
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
// SPDX-License-Identifier: Unlicense
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
|
||||
input clk;
|
||||
integer cyc; initial cyc=1;
|
||||
|
@ -41,16 +41,16 @@ module t (/*AUTOARG*/
|
|||
endmodule
|
||||
|
||||
module Test (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
|
||||
reg [31:0] dly0 = 0;
|
||||
reg [31:0] dly1 = 1;
|
||||
reg [31:0] dly2 = -1;
|
||||
reg [31:0] dly0 = 0;
|
||||
reg [31:0] dly1 = 0;
|
||||
reg [31:0] dly2 = 0;
|
||||
|
||||
// If called in an assertion, sequence, or property, the appropriate clocking event.
|
||||
// Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit.
|
||||
|
@ -60,33 +60,34 @@ module Test (/*AUTOARG*/
|
|||
|
||||
always @(posedge clk) begin
|
||||
dly0 <= in;
|
||||
dly1 <= in;
|
||||
dly2 <= in;
|
||||
dly1 <= dly0;
|
||||
dly2 <= dly1;
|
||||
// In clock expression
|
||||
$write("in=%0d, dly0=%0d, rose=%0d, past=%0d\n", in, dly0, $rose(dly0), $past(dly0));
|
||||
if ($rose(dly0[4])) $stop;
|
||||
if ($fell(dly1[4])) $stop;
|
||||
if ($stable(dly2)) $stop;
|
||||
if (!$changed(dly2)) $stop;
|
||||
if ($fell(dly0[4])) $stop;
|
||||
if (!$stable(dly0[4])) $stop;
|
||||
if ($changed(dly0[4])) $stop;
|
||||
end
|
||||
|
||||
assert property (@(posedge clk) $rose(dly0) || dly0%2==0);
|
||||
assert property (@(posedge clk) $fell(dly1) || dly1%2==1);
|
||||
assert property (@(posedge clk) !$stable(dly2));
|
||||
assert property (@(posedge clk) $changed(dly2));
|
||||
assert property (@(posedge clk) $rose(dly0) || dly0%2==0 || dly2 < 3);
|
||||
assert property (@(posedge clk) $fell(dly1) || dly1%2==1 || dly2 < 3);
|
||||
assert property (@(posedge clk) !$stable(dly2) || dly2 < 3);
|
||||
assert property (@(posedge clk) $changed(dly2) || dly2 < 3);
|
||||
|
||||
global clocking @(posedge clk); endclocking
|
||||
always @ ($global_clock) $display("%d", in);
|
||||
always @ ($global_clock) $display("gc in=%0d", in);
|
||||
//
|
||||
assert property (@(posedge clk) $rose(dly0, $global_clock) || dly0%2==0);
|
||||
assert property (@(posedge clk) $fell(dly1, $global_clock) || dly1%2==1);
|
||||
assert property (@(posedge clk) !$stable(dly2, $global_clock));
|
||||
assert property (@(posedge clk) $changed(dly2, $global_clock));
|
||||
assert property (@(posedge clk) $rose(dly0, $global_clock) || dly0%2==0 || dly2 < 3);
|
||||
assert property (@(posedge clk) $fell(dly1, $global_clock) || dly1%2==1 || dly2 < 3);
|
||||
assert property (@(posedge clk) !$stable(dly2, $global_clock) || dly2 < 3);
|
||||
assert property (@(posedge clk) $changed(dly2, $global_clock) || dly2 < 3);
|
||||
//
|
||||
assert property (@(posedge clk) $rose_gclk(dly0) || dly0%2==0);
|
||||
assert property (@(posedge clk) $fell_gclk(dly1) || dly1%2==1);
|
||||
assert property (@(posedge clk) !$stable_gclk(dly2));
|
||||
assert property (@(posedge clk) $changed_gclk(dly2));
|
||||
assert property (@(posedge clk) $rose_gclk(dly0) || dly0%2==0 || dly2 < 3);
|
||||
assert property (@(posedge clk) $fell_gclk(dly1) || dly1%2==1 || dly2 < 3);
|
||||
assert property (@(posedge clk) $past_gclk(dly1) == dly2 || dly2 < 3);
|
||||
assert property (@(posedge clk) !$stable_gclk(dly2) || dly2 < 3);
|
||||
assert property (@(posedge clk) $changed_gclk(dly2) || dly2 < 3);
|
||||
|
||||
// global_clocking_future_functions are not supported yet:
|
||||
// $changing_gclk global_clocking_future_function
|
||||
|
@ -99,21 +100,21 @@ endmodule
|
|||
|
||||
|
||||
module Test2 (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
|
||||
reg [31:0] dly0;
|
||||
reg [31:0] dly1 = 1;
|
||||
reg [31:0] dly2;
|
||||
reg [31:0] dly0 = 0;
|
||||
reg [31:0] dly1 = 0;
|
||||
reg [31:0] dly2 = 0;
|
||||
|
||||
always @(posedge clk) begin
|
||||
dly0 <= in;
|
||||
dly1 <= in;
|
||||
dly2 <= in;
|
||||
dly1 <= dly0;
|
||||
dly2 <= dly1;
|
||||
if ($rose(dly0[31:4])) $stop;
|
||||
if ($fell(dly1[31:4])) $stop;
|
||||
if (!$stable(dly2[31:4])) $stop;
|
||||
|
@ -122,23 +123,21 @@ module Test2 (/*AUTOARG*/
|
|||
|
||||
default clocking @(posedge clk); endclocking
|
||||
|
||||
assert property ($rose(dly0[0]) || dly0%2==0);
|
||||
assert property ($fell(dly1[0]) || dly1%2==1);
|
||||
assert property ($stable(dly2[31:4]));
|
||||
assert property (!$changed(dly2[31:4]));
|
||||
assert property ($rose(dly0[0]) || dly0%2==0 || dly2 < 3);
|
||||
assert property ($fell(dly1[0]) || dly1%2==1 || dly2 < 3);
|
||||
assert property ($stable(dly2[31:4]) || dly2 < 3);
|
||||
assert property (!$changed(dly2[31:4]) || dly2 < 3);
|
||||
endmodule
|
||||
|
||||
module Test3 (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
||||
input clk;
|
||||
input [31:0] in;
|
||||
|
||||
// Check the named form of global clocking
|
||||
global clocking gck @(posedge clk); endclocking
|
||||
always @ (gck) $display("%d", in);
|
||||
always @ ($global_clock) $display("%d", in);
|
||||
|
||||
endmodule
|
||||
|
|
Loading…
Reference in New Issue