Support global clocking and $global_clock.

This commit is contained in:
Wilson Snyder 2023-01-28 12:22:23 -05:00
parent bea225e191
commit f20997a2f0
13 changed files with 139 additions and 24 deletions

View File

@ -14,6 +14,7 @@ Verilator 5.007 devel
**Minor:**
* Support unpacked unions.
* Support global clocking and $global_clock.
Verilator 5.006 2022-01-22

View File

@ -350,8 +350,7 @@ private:
AstNodeExpr* const exprp = nodep->exprp()->unlinkFrBack();
AstNodeExpr* inp = newSampledExpr(exprp);
AstVar* invarp = nullptr;
AstSenTree* const sentreep = nodep->sentreep();
sentreep->unlinkFrBack();
AstSenTree* const sentreep = nodep->sentreep()->unlinkFrBack();
AstAlways* const alwaysp
= new AstAlways{nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr};
m_modp->addStmtsp(alwaysp);

View File

@ -822,19 +822,23 @@ class AstClocking final : public AstNode {
// @astgen op4 := eventp : Optional[AstVar]
std::string m_name; // Clocking block name
const bool m_isDefault = false; // True if default clocking
const bool m_isGlobal = false; // True if global clocking
public:
AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp,
AstClockingItem* itemsp, bool isDefault)
AstClockingItem* itemsp, bool isDefault, bool isGlobal)
: ASTGEN_SUPER_Clocking(fl)
, m_isDefault{isDefault} {
, m_isDefault{isDefault}
, m_isGlobal{isGlobal} {
m_name = name;
this->sensesp(sensesp);
addItemsp(itemsp);
}
ASTGEN_MEMBERS_AstClocking;
void dump(std::ostream& str) const override;
std::string name() const override { return m_name; }
bool isDefault() const { return m_isDefault; }
bool isGlobal() const { return m_isGlobal; }
};
class AstClockingItem final : public AstNode {
// Parents: CLOCKING

View File

@ -1509,6 +1509,11 @@ void AstNodeCoverOrAssert::dump(std::ostream& str) const {
this->AstNodeStmt::dump(str);
if (immediate()) str << " [IMMEDIATE]";
}
void AstClocking::dump(std::ostream& str) const {
this->AstNode::dump(str);
if (isDefault()) str << " [DEFAULT]";
if (isGlobal()) str << " [GLOBAL]";
}
void AstDisplay::dump(std::ostream& str) const {
this->AstNodeStmt::dump(str);
// str << " " << displayType().ascii();

View File

@ -1137,11 +1137,23 @@ class LinkDotFindVisitor final : public VNVisitor {
iterate(nodep->sensesp());
iterateAndNextNull(nodep->itemsp());
// If the block has no name, one cannot reference the clockvars
if (nodep->name().empty()) return;
VL_RESTORER(m_curSymp);
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
m_curSymp->fallbackp(nullptr);
iterateAndNextNull(nodep->itemsp());
VSymEnt* itSymp = nullptr;
if (nodep->isGlobal() //
&& m_statep->forPrimary()) { // else flattening may see two globals
m_statep->checkDuplicate(m_curSymp, nodep, "__024global_clock");
itSymp
= m_statep->insertBlock(m_curSymp, "__024global_clock", nodep, m_classOrPackagep);
itSymp->fallbackp(nullptr);
}
if (!nodep->name().empty()) {
itSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
itSymp->fallbackp(nullptr);
}
if (itSymp) {
VL_RESTORER(m_curSymp);
m_curSymp = itSymp;
iterateAndNextNull(nodep->itemsp());
}
}
void visit(AstClockingItem* nodep) override {
if (nodep->varp()) {

View File

@ -236,6 +236,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"$fwriteb" { FL; return yD_FWRITEB; }
"$fwriteh" { FL; return yD_FWRITEH; }
"$fwriteo" { FL; return yD_FWRITEO; }
"$global_clock" { FL; return yD_GLOBAL_CLOCK; }
"$hold" { FL; return yaTIMINGSPEC; }
"$hypot" { FL; return yD_HYPOT; }
"$itor" { FL; return yD_ITOR; }

View File

@ -844,6 +844,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yD_FWRITEB "$fwriteb"
%token<fl> yD_FWRITEH "$fwriteh"
%token<fl> yD_FWRITEO "$fwriteo"
%token<fl> yD_GLOBAL_CLOCK "$global_clock"
%token<fl> yD_HIGH "$high"
%token<fl> yD_HYPOT "$hypot"
%token<fl> yD_INCREMENT "$increment"
@ -4101,6 +4102,8 @@ system_f_call_or_t<nodeExprp>: // IEEE: part of system_tf_call (can be task
| yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF{$1, *$5, $3, $6}; }
| yD_FSEEK '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFSeek{$1, $3, $5, $7}; }
| yD_FTELL '(' idClassSel ')' { $$ = new AstFTell{$1, $3}; }
| yD_GLOBAL_CLOCK parenE
{ $$ = new AstParseRef{$<fl>1, VParseRefExp::PX_TEXT, "__024global_clock", nullptr, nullptr}; }
| yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_HIGH, $3, nullptr}; }
| yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_HIGH, $3, $5}; }
| yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD{$1, $3, $5}; }
@ -5441,17 +5444,15 @@ endLabelE<strp>:
clocking_declaration<nodep>: // IEEE: clocking_declaration
yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
{ $$ = new AstClocking{$<fl>2, *$2, $3, $5, false}; }
{ $$ = new AstClocking{$<fl>2, *$2, $3, $5, false, false}; }
| yDEFAULT yCLOCKING clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
{ $$ = new AstClocking{$<fl>2, "", $3, $5, true}; }
{ $$ = new AstClocking{$<fl>2, "", $3, $5, true, false}; }
| yDEFAULT yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
{ $$ = new AstClocking{$<fl>3, *$3, $4, $6, true}; }
{ $$ = new AstClocking{$<fl>3, *$3, $4, $6, true, false}; }
| yGLOBAL__CLOCKING yCLOCKING clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
{ $$ = nullptr;
BBUNSUP($<fl>2, "Unsupported: global clocking"); }
{ $$ = new AstClocking{$<fl>2, "", $3, $5, false, true}; }
| yGLOBAL__CLOCKING yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
{ $$ = nullptr;
BBUNSUP($<fl>3, "Unsupported: global clocking"); }
{ $$ = new AstClocking{$<fl>3, *$3, $4, $6, false, true}; }
;
clocking_event<senItemp>: // IEEE: clocking_event

View File

@ -0,0 +1,22 @@
%Error: t/t_clocking_bad5.v:29:20: Duplicate declaration of CLOCKING 'ck': '$global_clock'
29 | global clocking ogck @(posedge clk); endclocking
| ^~~~
t/t_clocking_bad5.v:26:20: ... Location of original declaration
26 | global clocking ck @(posedge clk); endclocking
| ^~
%Error: t/t_clocking_bad5.v:32:20: Duplicate declaration of CLOCKING 'ogck': '$global_clock'
32 | global clocking ck @(posedge clk); endclocking
| ^~
t/t_clocking_bad5.v:29:20: ... Location of original declaration
29 | global clocking ogck @(posedge clk); endclocking
| ^~~~
%Error: t/t_clocking_bad5.v:32:20: Duplicate declaration of CLOCKING 'ck': 'ck'
32 | global clocking ck @(posedge clk); endclocking
| ^~
t/t_clocking_bad5.v:26:20: ... Location of original declaration
26 | global clocking ck @(posedge clk); endclocking
| ^~
%Error: t/t_clocking_bad5.v:16:14: Can't find definition of variable: '$global_clock'
16 | always @ ($global_clock) $display;
| ^~~~~~~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
lint(
verilator_flags2 => ["--timing"],
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,34 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
sub sub(.*);
// Bad - no global clock
always @ ($global_clock) $display;
endmodule
module sub(/*AUTOARG*/
// Inputs
clk
);
input clk;
global clocking ck @(posedge clk); endclocking
// Bad - global duplicate
global clocking ogck @(posedge clk); endclocking
// Bad - name duplicate
global clocking ck @(posedge clk); endclocking
endmodule

View File

@ -14,10 +14,4 @@
%Error-UNSUPPORTED: t/t_clocking_unsup1.v:18:15: Unsupported: clocking event edge override
18 | output edge #1 b;
| ^~~~
%Error-UNSUPPORTED: t/t_clocking_unsup1.v:13:20: Unsupported: global clocking
13 | global clocking cb @(posedge clk);
| ^~
%Error-UNSUPPORTED: t/t_clocking_unsup1.v:21:11: Unsupported: global clocking
21 | global clocking @(posedge clk);
| ^~~~~~~~
%Error: Exiting due to

View File

@ -18,6 +18,4 @@ module t(/*AUTOARG*/
output edge #1 b;
endclocking
global clocking @(posedge clk);
endclocking
endmodule

View File

@ -23,6 +23,11 @@ module t (/*AUTOARG*/
.clk (clk),
.in (in[31:0]));
Test3 test3 (/*AUTOINST*/
// Inputs
.clk (clk),
.in (in[31:0]));
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
@ -69,6 +74,10 @@ module Test (/*AUTOARG*/
assert property (@(posedge clk) $fell(dly1) || dly1%2==1);
assert property (@(posedge clk) !$stable(dly2));
assert property (@(posedge clk) $changed(dly2));
global clocking @(posedge clk); endclocking
always @ ($global_clock) $display("%d", in);
endmodule
@ -101,3 +110,18 @@ module Test2 (/*AUTOARG*/
assert property ($stable(dly2[31:4]));
assert property (!$changed(dly2[31:4]));
endmodule
module Test3 (/*AUTOARG*/
// 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