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