forked from github/verilator
Support assignment expressions.
This commit is contained in:
parent
21d80cdfa1
commit
aacb38b776
1
Changes
1
Changes
@ -18,6 +18,7 @@ Verilator 5.003 devel
|
||||
* Support randcase.
|
||||
* Support pre_randomize and post_randomize.
|
||||
* Support $timeunit and $timeprecision.
|
||||
* Support assignment expressions.
|
||||
* Add ENUMVALUE warning when value misused for enum (#726).
|
||||
* Internal AST improvements, also affect XML format (#3721). [Geza Lore]
|
||||
* Change ENDLABEL from warning into an error.
|
||||
|
@ -237,6 +237,7 @@ private:
|
||||
// METHODS
|
||||
void iterateNewStmt(AstNode* nodep) {
|
||||
if (m_scopep) {
|
||||
VL_RESTORER(m_logicVertexp);
|
||||
UINFO(4, " STMT " << nodep << endl);
|
||||
m_logicVertexp = new CdcLogicVertex(&m_graph, m_scopep, nodep, m_domainp);
|
||||
if (m_domainp && m_domainp->hasClocked()) { // To/from a flop
|
||||
@ -247,7 +248,6 @@ private:
|
||||
m_logicVertexp->dstDomainSet(true);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
m_logicVertexp = nullptr;
|
||||
|
||||
if (false && debug() >= 9) {
|
||||
UINFO(9, "Trace Logic:\n");
|
||||
@ -680,6 +680,7 @@ private:
|
||||
}
|
||||
}
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
VL_RESTORER(m_inDly);
|
||||
m_inDly = true;
|
||||
iterateChildren(nodep);
|
||||
m_inDly = false;
|
||||
|
@ -505,6 +505,8 @@ private:
|
||||
nodep->deleteTree();
|
||||
}
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
VL_RESTORER(m_inDly);
|
||||
VL_RESTORER(m_nextDlyp);
|
||||
m_inDly = true;
|
||||
m_nextDlyp
|
||||
= VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe nullptr.
|
||||
@ -537,8 +539,6 @@ private:
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
m_inDly = false;
|
||||
m_nextDlyp = nullptr;
|
||||
}
|
||||
|
||||
void visit(AstVarRef* nodep) override {
|
||||
|
@ -190,18 +190,18 @@ class DataflowExtractVisitor final : public VNVisitor {
|
||||
}
|
||||
|
||||
void visit(AstAssignForce* nodep) override {
|
||||
VL_RESTORER(m_inForceReleaseLhs);
|
||||
iterate(nodep->rhsp());
|
||||
UASSERT_OBJ(!m_inForceReleaseLhs, nodep, "Should not nest");
|
||||
m_inForceReleaseLhs = true;
|
||||
iterate(nodep->lhsp());
|
||||
m_inForceReleaseLhs = false;
|
||||
}
|
||||
|
||||
void visit(AstRelease* nodep) override {
|
||||
VL_RESTORER(m_inForceReleaseLhs);
|
||||
UASSERT_OBJ(!m_inForceReleaseLhs, nodep, "Should not nest");
|
||||
m_inForceReleaseLhs = true;
|
||||
iterate(nodep->lhsp());
|
||||
m_inForceReleaseLhs = false;
|
||||
}
|
||||
|
||||
void visit(AstNodeExpr* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
@ -828,12 +828,13 @@ private:
|
||||
|
||||
void visit(AstNodeStmt* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
VL_RESTORER(m_stmtp);
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
VL_RESTORER(m_stmtp);
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
bool did = false;
|
||||
@ -869,7 +870,6 @@ private:
|
||||
}
|
||||
// Cleanup common code
|
||||
if (did) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
|
||||
//--------------------
|
||||
|
@ -396,15 +396,15 @@ class OrderBuildVisitor final : public VNVisitor {
|
||||
void visit(AstAssignW* nodep) override { iterateLogic(nodep); }
|
||||
void visit(AstAssignPre* nodep) override {
|
||||
UASSERT_OBJ(!m_inPre, nodep, "Should not nest");
|
||||
VL_RESTORER(m_inPre);
|
||||
m_inPre = true;
|
||||
iterateLogic(nodep);
|
||||
m_inPre = false;
|
||||
}
|
||||
void visit(AstAssignPost* nodep) override {
|
||||
UASSERT_OBJ(!m_inPost, nodep, "Should not nest");
|
||||
VL_RESTORER(m_inPost);
|
||||
m_inPost = true;
|
||||
iterateLogic(nodep);
|
||||
m_inPost = false;
|
||||
}
|
||||
|
||||
//--- Verilator concoctions
|
||||
|
@ -759,6 +759,9 @@ private:
|
||||
if (jumpingOver(nodep)) return;
|
||||
if (!optimizable()) return; // Accelerate
|
||||
checkNodeInfo(nodep);
|
||||
|
||||
VL_RESTORER(m_inDlyAssign);
|
||||
|
||||
if (VN_IS(nodep, AssignForce)) {
|
||||
clearOptimizable(nodep, "Force");
|
||||
} else if (VN_IS(nodep, AssignDly)) {
|
||||
@ -793,7 +796,6 @@ private:
|
||||
assignOutValue(nodep, vscp, fetchValue(nodep->rhsp()));
|
||||
}
|
||||
}
|
||||
m_inDlyAssign = false;
|
||||
}
|
||||
void visit(AstArraySel* nodep) override {
|
||||
checkNodeInfo(nodep);
|
||||
|
@ -156,9 +156,9 @@ class SliceVisitor final : public VNVisitor {
|
||||
// This will potentially call this function again to resolve next level of slicing
|
||||
return;
|
||||
}
|
||||
VL_RESTORER(m_assignp);
|
||||
m_assignp = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_assignp = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,10 +340,10 @@ protected:
|
||||
// of what is before vs. after
|
||||
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
VL_RESTORER(m_inDly);
|
||||
m_inDly = true;
|
||||
UINFO(4, " ASSIGNDLY " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
m_inDly = false;
|
||||
}
|
||||
void visit(AstVarRef* nodep) override {
|
||||
if (!m_stmtStackps.empty()) {
|
||||
|
@ -252,6 +252,7 @@ private:
|
||||
|
||||
// VISITORS
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
VL_RESTORER(m_ops);
|
||||
m_ops = 0;
|
||||
m_assignStep++;
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
@ -360,7 +361,7 @@ private:
|
||||
doDeletes();
|
||||
}
|
||||
void visit(AstNode* nodep) override {
|
||||
m_ops++;
|
||||
++m_ops;
|
||||
if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
@ -189,9 +189,9 @@ private:
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
void visit(AstAssignW* nodep) override {
|
||||
VL_RESTORER(m_assignwp);
|
||||
m_assignwp = nodep;
|
||||
VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep.
|
||||
m_assignwp = nullptr;
|
||||
}
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
// Includes handling AstMethodCall, AstNew
|
||||
|
@ -1229,6 +1229,8 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
void visit(AstOr* nodep) override { visitAndOr(nodep, false); }
|
||||
|
||||
void visitAssign(AstNodeAssign* nodep) {
|
||||
VL_RESTORER(m_alhs);
|
||||
VL_RESTORER(m_currentStrength);
|
||||
if (m_graphing) {
|
||||
if (AstAssignW* assignWp = VN_CAST(nodep, AssignW)) addToAssignmentList(assignWp);
|
||||
|
||||
@ -1279,9 +1281,6 @@ class TristateVisitor final : public TristateBaseVisitor {
|
||||
}
|
||||
}
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
// back to default strength
|
||||
m_currentStrength = VStrength::STRONG;
|
||||
m_alhs = false;
|
||||
}
|
||||
}
|
||||
void visit(AstAssignW* nodep) override { visitAssign(nodep); }
|
||||
|
117
src/verilog.y
117
src/verilog.y
@ -2691,18 +2691,30 @@ genvar_initialization<nodep>: // ==IEEE: genvar_initialization
|
||||
;
|
||||
|
||||
genvar_iteration<nodep>: // ==IEEE: genvar_iteration
|
||||
varRefBase '=' expr { $$ = new AstAssign($2,$1,$3); }
|
||||
| varRefBase yP_PLUSEQ expr { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_MINUSEQ expr { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_TIMESEQ expr { $$ = new AstAssign($2,$1,new AstMul ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_DIVEQ expr { $$ = new AstAssign($2,$1,new AstDiv ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_MODEQ expr { $$ = new AstAssign($2,$1,new AstModDiv ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_ANDEQ expr { $$ = new AstAssign($2,$1,new AstAnd ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_OREQ expr { $$ = new AstAssign($2,$1,new AstOr ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_XOREQ expr { $$ = new AstAssign($2,$1,new AstXor ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_SLEFTEQ expr { $$ = new AstAssign($2,$1,new AstShiftL ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_SRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftR ($2,$1->cloneTree(true),$3)); }
|
||||
| varRefBase yP_SSRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftRS($2,$1->cloneTree(true),$3)); }
|
||||
varRefBase '=' expr
|
||||
{ $$ = new AstAssign{$2, $1, $3}; }
|
||||
| varRefBase yP_PLUSEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_MINUSEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_TIMESEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_DIVEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_MODEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_ANDEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_OREQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_XOREQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_SLEFTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_SRIGHTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTree(true), $3}}; }
|
||||
| varRefBase yP_SSRIGHTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTree(true), $3}}; }
|
||||
// // inc_or_dec_operator
|
||||
// When support ++ as a real AST type, maybe AstWhile::precondsp() becomes generic AstNodeExprStmt?
|
||||
| yP_PLUSPLUS varRefBase
|
||||
@ -3425,17 +3437,28 @@ foperator_assignment<nodep>: // IEEE: operator_assignment (for first part of
|
||||
| fexprLvalue '=' yD_FOPEN '(' expr ',' expr ')' { $$ = new AstFOpen($3,$1,$5,$7); }
|
||||
//
|
||||
//UNSUP ~f~exprLvalue yP_PLUS(etc) expr { UNSUP }
|
||||
| fexprLvalue yP_PLUSEQ expr { $$ = new AstAssign($2,$1,new AstAdd ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_MINUSEQ expr { $$ = new AstAssign($2,$1,new AstSub ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_TIMESEQ expr { $$ = new AstAssign($2,$1,new AstMul ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_DIVEQ expr { $$ = new AstAssign($2,$1,new AstDiv ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_MODEQ expr { $$ = new AstAssign($2,$1,new AstModDiv ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_ANDEQ expr { $$ = new AstAssign($2,$1,new AstAnd ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_OREQ expr { $$ = new AstAssign($2,$1,new AstOr ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_XOREQ expr { $$ = new AstAssign($2,$1,new AstXor ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_SLEFTEQ expr { $$ = new AstAssign($2,$1,new AstShiftL ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_SRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftR ($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_SSRIGHTEQ expr { $$ = new AstAssign($2,$1,new AstShiftRS($2,$1->cloneTree(true),$3)); }
|
||||
| fexprLvalue yP_PLUSEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstAdd{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_MINUSEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstSub{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_TIMESEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstMul{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_DIVEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstDiv{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_MODEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstModDiv{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_ANDEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstAnd{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_OREQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstOr{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_XOREQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstXor{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_SLEFTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftL{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_SRIGHTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftR{$2, $1->cloneTree(true), $3}}; }
|
||||
| fexprLvalue yP_SSRIGHTEQ expr
|
||||
{ $$ = new AstAssign{$2, $1, new AstShiftRS{$2, $1->cloneTree(true), $3}}; }
|
||||
//UNSUP replace above with:
|
||||
//UNSUP BISONPRE_COPY(operator_assignment,{s/~f~/f/g}) // {copied}
|
||||
;
|
||||
@ -4403,18 +4426,42 @@ expr<nodeExprp>: // IEEE: part of expression/constant_expression/
|
||||
//
|
||||
// // IEEE: '(' operator_assignment ')'
|
||||
// // Need exprScope of variable_lvalue to prevent conflict
|
||||
//UNSUP '(' ~p~exprScope '=' expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_PLUSEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_MINUSEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_TIMESEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_DIVEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_MODEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_ANDEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_OREQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_XOREQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_SLEFTEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_SRIGHTEQ expr ')' { UNSUP }
|
||||
//UNSUP '(' ~p~exprScope yP_SSRIGHTEQ expr ')' { UNSUP }
|
||||
| '(' ~p~exprScope '=' expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, $4},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_PLUSEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAdd{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_MINUSEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstSub{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_TIMESEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstMul{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_DIVEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstDiv{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_MODEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstModDiv{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_ANDEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstAnd{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_OREQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstOr{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_XOREQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstXor{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_SLEFTEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftL{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_SRIGHTEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftR{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
| '(' ~p~exprScope yP_SSRIGHTEQ expr ')'
|
||||
{ $$ = new AstExprStmt{$1, new AstAssign{$3, $2, new AstShiftRS{$3, $2->cloneTree(true), $4}},
|
||||
$2->cloneTree(true)}; }
|
||||
//
|
||||
// // IEEE: expression binary_operator expression
|
||||
| ~l~expr '+' ~r~expr { $$ = new AstAdd ($2,$1,$3); }
|
||||
|
21
test_regress/t/t_assign_expr.pl
Executable file
21
test_regress/t/t_assign_expr.pl
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2022 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(simulator => 1);
|
||||
|
||||
compile(
|
||||
);
|
||||
|
||||
execute(
|
||||
check_finished => 1,
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
77
test_regress/t/t_assign_expr.v
Normal file
77
test_regress/t/t_assign_expr.v
Normal file
@ -0,0 +1,77 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t(/*AUTOARG*/);
|
||||
|
||||
int a;
|
||||
int b;
|
||||
int i;
|
||||
|
||||
initial begin
|
||||
a = 10;
|
||||
i = (a = 2);
|
||||
`checkd(a, 2); `checkd(i, 2);
|
||||
|
||||
a = 10;
|
||||
i = (a += 2);
|
||||
`checkd(a, 12); `checkd(i, 12);
|
||||
|
||||
a = 10;
|
||||
i = (a -= 2);
|
||||
`checkd(a, 8); `checkd(i, 8);
|
||||
|
||||
a = 10;
|
||||
i = (a *= 2);
|
||||
`checkd(a, 20); `checkd(i, 20);
|
||||
|
||||
a = 10;
|
||||
i = (a /= 2);
|
||||
`checkd(a, 5); `checkd(i, 5);
|
||||
|
||||
a = 11;
|
||||
i = (a %= 2);
|
||||
`checkd(a, 1); `checkd(i, 1);
|
||||
|
||||
a = 10;
|
||||
i = (a &= 2);
|
||||
`checkd(a, 2); `checkd(i, 2);
|
||||
|
||||
a = 8;
|
||||
i = (a |= 2);
|
||||
`checkd(a, 10); `checkd(i, 10);
|
||||
|
||||
a = 10;
|
||||
i = (a ^= 2);
|
||||
`checkd(a, 8); `checkd(i, 8);
|
||||
|
||||
a = 10;
|
||||
i = (a <<= 2);
|
||||
`checkd(a, 40); `checkd(i, 40);
|
||||
|
||||
a = 10;
|
||||
i = (a >>= 2);
|
||||
`checkd(a, 2); `checkd(i, 2);
|
||||
|
||||
a = 10;
|
||||
i = (a >>>= 2);
|
||||
`checkd(a, 2); `checkd(i, 2);
|
||||
|
||||
a = 10;
|
||||
i = (a = (b = 5));
|
||||
`checkd(a, 5); `checkd(i, 5); `checkd(b, 5);
|
||||
|
||||
a = 10;
|
||||
b = 6;
|
||||
i = ((a += (b += 1) + 1));
|
||||
`checkd(a, 18); `checkd(i, 18); `checkd(b, 7);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user