Support simple cast operators, bug335.
This commit is contained in:
parent
9704f59566
commit
c83f12a55c
2
Changes
2
Changes
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue