Support simple cast operators, bug335.

This commit is contained in:
Wilson Snyder 2011-03-17 22:25:49 -04:00
parent 9704f59566
commit c83f12a55c
8 changed files with 120 additions and 2 deletions

View File

@ -11,6 +11,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Support loop unrolling on width mismatches, bug 333. [Joe Eiler] **** Support loop unrolling on width mismatches, bug 333. [Joe Eiler]
**** Support simple cast operators, bug335. [Alex Solomatnikov]
**** Accelerate bit-selected inversions. **** Accelerate bit-selected inversions.
**** Add error on circular parameter definitions, bug329. [Alex Solomatnikov] **** Add error on circular parameter definitions, bug329. [Alex Solomatnikov]

View File

@ -2235,6 +2235,11 @@ Increment/decrement can only be used as standalone statements or in for
loops. They cannot be used as side effect operators inside more complicate loops. They cannot be used as side effect operators inside more complicate
expressions ("a = b++;"). expressions ("a = b++;").
=item cast operator
Casting is supported only between simple scalar types, signed and unsigned,
not arrays nor structs.
=item chandle =item chandle
Treated as a "longint"; does not yet warn about operations that are Treated as a "longint"; does not yet warn about operations that are

View File

@ -2622,8 +2622,23 @@ struct AstOneHot0 : public AstNodeUniop {
virtual int instrCount() const { return widthInstrs()*3; } virtual int instrCount() const { return widthInstrs()*3; }
}; };
struct AstCast : public AstNode {
// Cast to appropriate data type - note lhsp is value, to match AstTypedef, AstCCast, etc
AstCast(FileLine* fl, AstNode* lhsp, AstNodeDType* dtypep) : AstNode(fl) {
setOp1p(lhsp); setOp2p(dtypep);
if (dtypep) { widthSignedFrom(dtypep); }
}
ASTNODE_NODE_FUNCS(Cast, CAST)
virtual string emitVerilog() { return "((%r)'(%l))"; }
virtual string emitC() { V3ERROR_NA; return ""; }
virtual bool cleanOut() { V3ERROR_NA; return true;} virtual bool cleanLhs() {return true;}
virtual bool sizeMattersLhs() {return false;}
AstNode* lhsp() const { return op1p(); }
AstNodeDType* dtypep() const { return op2p()->castNodeDType(); }
};
struct AstCCast : public AstNodeUniop { struct AstCCast : public AstNodeUniop {
// Cast to appropriate data type // Cast to C-based data type
private: private:
int m_size; int m_size;
public: public:

View File

@ -163,6 +163,11 @@ private:
nodep->itemp()->iterate(*this); nodep->itemp()->iterate(*this);
nodep->signedFrom(nodep->itemp()); nodep->signedFrom(nodep->itemp());
} }
virtual void visit(AstCast* nodep, AstNUser*) {
nodep->lhsp()->iterate(*this);
nodep->dtypep()->iterate(*this);
nodep->signedFrom(nodep->dtypep());
}
virtual void visit(AstConst* nodep, AstNUser*) { virtual void visit(AstConst* nodep, AstNUser*) {
// The node got setup with the signed state of the node. // The node got setup with the signed state of the node.
// However a later operation may have changed the node->signed w/o changing // However a later operation may have changed the node->signed w/o changing

View File

@ -524,6 +524,25 @@ private:
nodep->iterateChildren(*this, vup); nodep->iterateChildren(*this, vup);
nodep->widthFrom(nodep->dtypep()->skipRefp()); nodep->widthFrom(nodep->dtypep()->skipRefp());
} }
virtual void visit(AstCast* nodep, AstNUser* vup) {
nodep->lhsp()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
nodep->dtypep()->iterateAndNext(*this,WidthVP(ANYSIZE,0,BOTH).p());
// When more general casts are supported, the cast elimination will be done later.
// For now, replace it ASAP, so widthing can propagate easily
// The cast may change signing, but we don't know the sign yet. Make it so.
// Note we don't sign lhsp() that would make the algorithm O(n^2) if lots of casting.
V3Width::widthParamsEdit(nodep->dtypep()); // MAY CHANGE dtypep()
AstBasicDType* basicp = nodep->dtypep()->basicp(); if (!basicp) nodep->v3fatalSrc("Unimplemented: Casting non-simple data type");
nodep->widthSignedFrom(basicp);
widthCheck(nodep,"Cast",nodep->lhsp(),nodep->width(),nodep->width(),true);
AstNode* newp = nodep->lhsp()->unlinkFrBack();
if (basicp->isSigned()) {
newp = new AstSigned(nodep->fileline(), newp);
} else {
newp = new AstUnsigned(nodep->fileline(), newp);
}
nodep->replaceWith(newp);
}
virtual void visit(AstVar* nodep, AstNUser* vup) { virtual void visit(AstVar* nodep, AstNUser* vup) {
//if (debug()) nodep->dumpTree(cout," InitPre: "); //if (debug()) nodep->dumpTree(cout," InitPre: ");
// Must have deterministic constant width // Must have deterministic constant width

View File

@ -1078,6 +1078,31 @@ signing<signstate>: // ==IEEE: signing
//************************************************ //************************************************
// Data Types // Data Types
casting_type<dtypep>: // IEEE: casting_type
simple_type { $$ = $1; }
// // IEEE: constant_primary
// // In expr:cast this is expanded to just "expr"
//
// // IEEE: signing
//See where casting_type used
//^^ ySIGNED { $$ = new AstSigned($1,$3); }
//^^ yUNSIGNED { $$ = new AstUnsigned($1,$3); }
//UNSUP ySTRING { $$ = $1; }
//UNSUP yCONST__ETC/*then `*/ { $$ = $1; }
;
simple_type<dtypep>: // ==IEEE: simple_type
// // IEEE: integer_type
integer_atom_type { $$ = $1; }
| integer_vector_type { $$ = $1; }
//UNSUP non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; }
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
data_type<dtypep>: // ==IEEE: data_type data_type<dtypep>: // ==IEEE: data_type
// // This expansion also replicated elsewhere, IE data_type__AndID // // This expansion also replicated elsewhere, IE data_type__AndID
data_typeNoRef { $$ = $1; } data_typeNoRef { $$ = $1; }
@ -2455,7 +2480,10 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
| '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL | '_' '(' statePushVlg expr statePop ')' { $$ = $4; } // Arbitrary Verilog inside PSL
// //
// // IEEE: cast/constant_cast // // IEEE: cast/constant_cast
//UNSUP casting_type yP_TICK '(' expr ')' { UNSUP } | casting_type yP_TICK '(' expr ')' { $$ = new AstCast($2,$4,$1); }
// // expanded from casting_type
| ySIGNED yP_TICK '(' expr ')' { $$ = new AstSigned($1,$4); }
| yUNSIGNED yP_TICK '(' expr ')' { $$ = new AstUnsigned($1,$4); }
// // Spec only allows primary with addition of a type reference // // Spec only allows primary with addition of a type reference
// // We'll be more general, and later assert LHS was a type. // // We'll be more general, and later assert LHS was a type.
//UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP } //UNSUP ~l~expr yP_TICK '(' expr ')' { UNSUP }

18
test_regress/t/t_cast.pl Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 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.
compile (
);
execute (
check_finished=>1,
);
ok(1);
1;

26
test_regress/t/t_cast.v Normal file
View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2011 by Wilson Snyder.
module t;
typedef logic [3:0] mc_t;
typedef mc_t tocast_t;
mc_t o;
initial begin
if (4'shf > 4'sh0) $stop;
if (signed'(4'hf) > 4'sh0) $stop;
if (4'hf < 4'h0) $stop;
if (unsigned'(4'shf) < 4'h0) $stop;
o = tocast_t'(4'b1);
if (o != 4'b1) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule