Compare commits

...

28 Commits

Author SHA1 Message Date
Todd Strader
2de586e678 WIP - type compare case grammar 2020-04-08 10:06:48 -04:00
Todd Strader
14285f24cd Fix queues type matching 2020-04-01 15:48:28 -04:00
Todd Strader
6c6f7f8ae9 Tests for dynamic arrays, assosicative arrays and queues 2020-04-01 15:48:15 -04:00
Todd Strader
42962bf5ee Test enums, unions and package namespaces 2020-04-01 15:08:02 -04:00
Todd Strader
61394bdece const var fix 2020-04-01 14:38:37 -04:00
Todd Strader
240c4e98ac const tests 2020-04-01 14:37:50 -04:00
Todd Strader
9bd94be5d2 case test 2020-04-01 11:49:45 -04:00
Todd Strader
8744ce85d0 Simplification 2020-04-01 11:49:32 -04:00
Todd Strader
87e8e219dd trip equal impl 2020-03-31 17:39:37 -04:00
Todd Strader
7997ba08cb trip equal tests 2020-03-31 17:39:23 -04:00
Todd Strader
bfe2760098 Resolve RefDTypes safely 2020-03-31 16:57:32 -04:00
Todd Strader
a105fdf731 More tests are working 2020-03-31 16:57:19 -04:00
Todd Strader
fd175de17e More refdtype handling 2020-03-31 12:24:36 -04:00
Todd Strader
e17f6ed030 Make matching() virtual for AstNodeDType 2020-03-31 11:54:47 -04:00
Todd Strader
5d8d0585c1 Test TODOs 2020-03-31 11:54:14 -04:00
Todd Strader
d3ac16d6d9 Move matching check into AstBasicDType 2020-03-27 16:00:59 -04:00
Todd Strader
6dd4ff021f Test fix 2020-03-27 16:00:02 -04:00
Todd Strader
693d52b57c More stuff working 2020-03-27 14:51:44 -04:00
Todd Strader
67c18ada59 Tests, tests, tests 2020-03-27 14:51:38 -04:00
Todd Strader
d08d07e89b More tests 2020-03-27 13:22:29 -04:00
Todd Strader
089fe9ae0f Check signedness 2020-03-27 13:22:16 -04:00
Todd Strader
dc517c8335 Still more test 2020-03-27 08:27:16 -04:00
Todd Strader
862892c9bd Check for the same entry in the type table 2020-03-27 08:24:07 -04:00
Todd Strader
fce1fa0953 More test 2020-03-27 07:59:26 -04:00
Todd Strader
3dcf14ec56 Progress 2020-03-27 07:39:36 -04:00
Todd Strader
d3a787698b Working on flattening types 2020-03-26 18:05:48 -04:00
Todd Strader
6727a41d7f Parser hack 2020-03-20 05:47:31 -04:00
Todd Strader
8535fad052 Type comparison test 2020-03-20 05:47:31 -04:00
6 changed files with 385 additions and 5 deletions

View File

@ -2094,6 +2094,15 @@ public:
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
static int uniqueNumInc() { return ++s_uniqueNum; }
const char* charIQWN() const { return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I"); }
bool matching(const AstNodeDType* typep) const {
if (VN_IS(typep, RefDType) || VN_IS(typep, ConstDType)) {
// Unwrap type wrappers
return typep->match(this);
} else {
return match(typep);
}
}
virtual bool match(const AstNodeDType* typep) const = 0;
};
class AstNodeUOrStructDType : public AstNodeDType {
@ -2148,6 +2157,7 @@ public:
int lsb() const { return 0; }
int msb() const { return dtypep()->width()-1; } // Packed classes look like arrays
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
virtual bool match(const AstNodeDType* typep) const { return typep == this; }
};
class AstNodeArrayDType : public AstNodeDType {
@ -2205,6 +2215,13 @@ public:
int lsb() const;
int elementsConst() const;
VNumRange declRange() const;
virtual bool matchingArrayType(const AstNodeArrayDType* matchp) const = 0;
virtual bool match(const AstNodeDType* typep) const {
const AstNodeArrayDType* arrayp = VN_CAST_CONST(typep, NodeArrayDType);
if (!arrayp) return typep->matching(this);
return arrayp && matchingArrayType(arrayp) && declRange() == arrayp->declRange()
&& subDTypep()->matching(arrayp->subDTypep());
}
};
class AstNodeSel : public AstNodeBiop {

View File

@ -305,6 +305,7 @@ public:
AstVarType varType() const { return m_varType; } // * = Type of variable
bool isParam() const { return true; }
bool isGParam() const { return (varType()==AstVarType::GPARAM); }
virtual bool match(const AstNodeDType* typep) const { return childDTypep()->matching(typep); }
};
class AstTypedef : public AstNode {
@ -389,6 +390,7 @@ public:
virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); }
virtual string name() const { return m_name; }
void name(const string& flag) { m_name = flag; }
virtual bool match(const AstNodeDType* typep) const { return typep == this; }
};
class AstAssocArrayDType : public AstNodeDType {
@ -449,6 +451,11 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const {
const AstAssocArrayDType* arrayp = VN_CAST_CONST(typep, AssocArrayDType);
return arrayp && subDTypep()->matching(arrayp->subDTypep())
&& keyDTypep()->matching(arrayp->keyDTypep());
}
};
class AstDynArrayDType : public AstNodeDType {
@ -499,6 +506,10 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const {
const AstDynArrayDType* arrayp = VN_CAST_CONST(typep, DynArrayDType);
return arrayp && subDTypep()->matching(arrayp->subDTypep());
}
};
class AstPackArrayDType : public AstNodeArrayDType {
@ -525,6 +536,9 @@ public:
}
ASTNODE_NODE_FUNCS(PackArrayDType)
virtual string prettyDTypeName() const;
virtual bool matchingArrayType(const AstNodeArrayDType* matchp) const {
return VN_IS(matchp, PackArrayDType);
}
};
class AstUnpackArrayDType : public AstNodeArrayDType {
@ -553,6 +567,9 @@ public:
}
ASTNODE_NODE_FUNCS(UnpackArrayDType)
virtual string prettyDTypeName() const;
virtual bool matchingArrayType(const AstNodeArrayDType* matchp) const {
return VN_IS(matchp, UnpackArrayDType);
}
};
class AstUnsizedArrayDType : public AstNodeDType {
@ -596,6 +613,10 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const {
const AstUnsizedArrayDType* arrayp = VN_CAST_CONST(typep, UnsizedArrayDType);
return arrayp && subDTypep()->matching(arrayp->subDTypep());
}
};
class AstBasicDType : public AstNodeDType {
@ -673,6 +694,14 @@ public:
virtual bool same(const AstNode* samep) const { // width/widthMin/numeric compared elsewhere
const AstBasicDType* sp = static_cast<const AstBasicDType*>(samep);
return m == sp->m; }
virtual bool match(const AstNodeDType* typep) const {
const AstBasicDType* matchp = VN_CAST_CONST(typep, BasicDType);
return matchp && isSigned() == matchp->isSigned()
&& (same(matchp) ||
(isIntNumeric() && matchp->isIntNumeric()
&& isFourstate() == matchp->isFourstate()
&& nrange() == matchp->nrange()));
}
virtual bool similarDType(AstNodeDType* samep) const {
return type()==samep->type() && same(samep); }
virtual string name() const { return m.m_keyword.ascii(); }
@ -700,6 +729,7 @@ public:
bool isString() const { return keyword().isString(); }
bool isSloppy() const { return keyword().isSloppy(); }
bool isZeroInit() const { return keyword().isZeroInit(); }
bool isIntNumeric() const { return keyword().isIntNumeric(); }
bool isRanged() const { return rangep() || m.m_nrange.ranged(); }
const VNumRange& nrange() const { return m.m_nrange; } // Generally the msb/lsb/etc funcs should be used instead
int msb() const { return (rangep() ? rangep()->msbConst() : m.m_nrange.hi()); }
@ -759,6 +789,7 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const { return subDTypep()->matching(typep); }
};
class AstClassRefDType : public AstNodeDType {
@ -798,6 +829,7 @@ public:
void packagep(AstPackage* nodep) { m_packagep = nodep; }
AstClass* classp() const { return m_classp; }
void classp(AstClass* nodep) { m_classp = nodep; }
virtual bool match(const AstNodeDType* typep) const { return typep == this; }
};
class AstIfaceRefDType : public AstNodeDType {
@ -850,6 +882,8 @@ public:
AstModport* modportp() const { return m_modportp; }
void modportp(AstModport* modportp) { m_modportp = modportp; }
bool isModport() { return !m_modportName.empty(); }
// Cannot take type() of interface
virtual bool match(const AstNodeDType* typep) const { return false; }
};
class AstQueueDType : public AstNodeDType {
@ -899,6 +933,10 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const {
const AstQueueDType* queuep = VN_CAST_CONST(typep, QueueDType);
return queuep && subDTypep()->matching(queuep->subDTypep());
}
};
class AstRefDType : public AstNodeDType {
@ -964,6 +1002,7 @@ public:
AstPackage* packagep() const { return m_packagep; }
void packagep(AstPackage* nodep) { m_packagep = nodep; }
AstNode* typeofp() const { return op2p(); }
virtual bool match(const AstNodeDType* typep) const { return refDTypep()->matching(typep); }
};
class AstStructDType : public AstNodeUOrStructDType {
@ -1041,6 +1080,7 @@ public:
virtual string tag() const { return m_tag; }
int lsb() const { return m_lsb; }
void lsb(int lsb) { m_lsb = lsb; }
virtual bool match(const AstNodeDType* typep) const { return subDTypep()->matching(typep); }
};
class AstVoidDType : public AstNodeDType {
@ -1063,6 +1103,7 @@ public:
virtual int widthAlignBytes() const { return 1; }
virtual int widthTotalBytes() const { return 1; }
virtual V3Hash sameHash() const { return V3Hash(); }
virtual bool match(const AstNodeDType* typep) const { return false; }
};
class AstEnumItem : public AstNode {
@ -1156,6 +1197,7 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); }
virtual bool match(const AstNodeDType* typep) const { return typep == this; }
};
class AstParseTypeDType : public AstNodeDType {
@ -1175,6 +1217,7 @@ public:
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
virtual int widthAlignBytes() const { return 0; }
virtual int widthTotalBytes() const { return 0; }
virtual bool match(const AstNodeDType* typep) const { return false; }
};
//######################################################################
@ -2981,6 +3024,18 @@ public:
void priorityPragma(bool flag) { m_priorityPragma = flag; }
};
class AstTypeCase : public AstNodeCase {
// Case statement for type references
// Parents: {statement list}
// exprp Children: MATHs
// casesp Children: CASEITEMs
public:
AstTypeCase(FileLine* fl, AstNodeDType* typep, AstNode* casesp)
: ASTGEN_SUPER(fl, typep, casesp) { }
ASTNODE_NODE_FUNCS(TypeCase)
virtual string verilogKwd() const { return "case"; }
};
class AstCaseItem : public AstNode {
// Single item of a case statement
// Parents: CASE
@ -5647,6 +5702,39 @@ public:
virtual int instrCount() const { return instrCountString(); }
virtual bool stringFlavor() const { return true; }
};
class AstEqT : public AstNodeBiCom {
public:
AstEqT(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); }
ASTNODE_NODE_FUNCS(EqT)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstEqT(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opEq(lhs, rhs); }
virtual string emitVerilog() { return "%k(%l %f== %r)"; }
// TOOD -- if we can't even emit C, should this be a child of AstNodeMath?
virtual string emitC() { return ""; }
virtual string emitSimpleOperator() { return "=="; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return false; }
virtual bool cleanRhs() const { return false; }
virtual bool sizeMattersLhs() const { return false; }
virtual bool sizeMattersRhs() const { return false; }
};
class AstNeqT : public AstNodeBiCom {
public:
AstNeqT(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
: ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetLogicBool(); }
ASTNODE_NODE_FUNCS(NeqT)
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { return new AstNeqT(this->fileline(), lhsp, rhsp); }
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { out.opNeq(lhs, rhs); }
virtual string emitVerilog() { return "%k(%l %f!= %r)"; }
virtual string emitC() { return ""; }
virtual string emitSimpleOperator() { return "!="; }
virtual bool cleanOut() const { return false; }
virtual bool cleanLhs() const { return false; }
virtual bool cleanRhs() const { return false; }
virtual bool sizeMattersLhs() const { return false; }
virtual bool sizeMattersRhs() const { return false; }
};
class AstShiftL : public AstNodeBiop {
public:
AstShiftL(FileLine* fl, AstNode* lhsp, AstNode* rhsp, int setwidth=0)

View File

@ -197,6 +197,7 @@ private:
bool m_doGenerate; // Do errors later inside generate statement
int m_dtTables; // Number of created data type tables
TableMap m_tableMap; // Created tables so can remove duplicates
bool m_leaveTypeof; // Don't clean up type-of children
// ENUMS
enum ExtendRule {
@ -254,6 +255,9 @@ private:
// ... These comparisons don't allow reals
virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); }
virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); }
// ... Type compares
virtual void visit(AstEqT* nodep) VL_OVERRIDE { visit_cmp_eq_type(nodep); }
virtual void visit(AstNeqT* nodep) VL_OVERRIDE { visit_cmp_eq_type(nodep); }
// ... Real compares
virtual void visit(AstEqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); }
virtual void visit(AstNeqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); }
@ -1301,7 +1305,8 @@ private:
userIterateAndNext(nodep->typeofp(), WidthVP(SELF, BOTH).p());
AstNode* typeofp = nodep->typeofp();
nodep->refDTypep(typeofp->dtypep());
VL_DO_DANGLING(typeofp->unlinkFrBack()->deleteTree(), typeofp);
if (!m_leaveTypeof)
VL_DO_DANGLING(typeofp->unlinkFrBack()->deleteTree(), typeofp);
// We had to use AstRefDType for this construct as pointers to this type
// in type table are still correct (which they wouldn't be if we replaced the node)
}
@ -3571,6 +3576,35 @@ private:
}
}
void visit_cmp_eq_type(AstNodeBiop* nodep) {
if (m_vup->prelim()) {
// don't clean up types which may not be in the type table
// we're going to remove this whole sub-tree anyway
m_leaveTypeof = true;
userIterateChildren(nodep, WidthVP(CONTEXT, PRELIM).p());
m_leaveTypeof = false;
bool equal = false;
// TODO -- remove
nodep->dumpTree(cout, "typeCompare: ");
AstRefDType* refLhsp = VN_CAST(nodep->lhsp(), RefDType);
AstRefDType* refRhsp = VN_CAST(nodep->rhsp(), RefDType);
if (refLhsp && refRhsp) {
if (refLhsp->matching(refRhsp)
// TODO -- is this even necessary in the end?
|| refLhsp->dtypep() == refRhsp->dtypep()) {
equal = true;
}
} else {
nodep->v3fatalSrc("Expected two types for type comparison");
}
bool isNot = VN_IS(nodep, NeqT);
uint32_t value = equal ^ isNot ? 1 : 0;
nodep->replaceWith(new AstConst(nodep->fileline(), AstConst::WidthedValue(),
1, value));
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
void visit_cmp_eq_gt(AstNodeBiop* nodep, bool realok) {
// CALLER: AstEq, AstGt, ..., AstLtS
// Real allowed if and only if real_lhs set
@ -4901,6 +4935,7 @@ public:
m_doGenerate = doGenerate;
m_dtTables = 0;
m_vup = NULL;
m_leaveTypeof = false;
}
AstNode* mainAcceptEdit(AstNode* nodep) {
return userIterateSubtreeReturnEdits(nodep, WidthVP(SELF, BOTH).p());

View File

@ -2708,6 +2708,7 @@ statement_item<nodep>: // IEEE: statement_item
if ($1 == uniq_UNIQUE) $2->uniquePragma(true);
if ($1 == uniq_UNIQUE0) $2->unique0Pragma(true);
if ($1 == uniq_PRIORITY) $2->priorityPragma(true); }
| typeCaseStart typeCase_itemListE yENDCASE { $$ = $1; if ($2) $1->addItemsp($2); }
//
// // IEEE: conditional_statement
| unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE
@ -2929,6 +2930,10 @@ caseStart<casep>: // IEEE: part of case_statement
| yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEZ,$3,NULL); }
;
typeCaseStart<casep>: // IEEE: part of case_statement
yCASE '(' type_reference ')' { $$ = new AstTypeCase($1,$3,NULL); }
;
caseAttrE:
/*empty*/ { }
| caseAttrE yVL_FULL_CASE { GRAMMARP->m_caseAttrp->fullPragma(true); }
@ -2945,6 +2950,11 @@ case_itemListE<caseitemp>: // IEEE: [ { case_item } ]
| case_itemList { $$ = $1; }
;
typeCase_itemListE<caseitemp>: // IEEE: [ { case_item } ]
/* empty */ { $$ = NULL; }
| typeCase_itemList { $$ = $1; }
;
case_insideListE<caseitemp>: // IEEE: [ { case_inside_item } ]
/* empty */ { $$ = NULL; }
| case_inside_itemList { $$ = $1; }
@ -2952,11 +2962,21 @@ case_insideListE<caseitemp>: // IEEE: [ { case_inside_item } ]
case_itemList<caseitemp>: // IEEE: { case_item + ... }
caseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
| yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($1,NULL,$3); }
| yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); }
| case_defaultItem { $$ = $1; }
| case_itemList caseCondList ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
| case_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); }
| case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$4)); }
| case_itemList case_defaultItem { $$ = $1;$1->addNext($2); }
;
case_defaultItem<caseitemp>:
yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($1,NULL,$3); }
| yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); }
;
typeCase_itemList<caseitemp>: // IEEE: { case_item + ... } but for type references
typeCaseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); }
| case_defaultItem { $$ = $1; }
| typeCase_itemList typeCaseCondList ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); }
| typeCase_itemList case_defaultItem { $$ = $1;$1->addNext($2); }
;
case_inside_itemList<caseitemp>: // IEEE: { case_inside_item + open_range_list ... }
@ -2992,6 +3012,11 @@ caseCondList<nodep>: // IEEE: part of case_item
| caseCondList ',' expr { $$ = $1;$1->addNext($3); }
;
typeCaseCondList<nodep>: // IEEE: also part of case_item
type_reference { $$ = $1; }
| typeCaseCondList ',' type_reference { $$ = $1;$1->addNext($3); }
;
patternNoExpr<nodep>: // IEEE: pattern **Excluding Expr*
'.' id/*variable*/ { $$ = NULL; $1->v3error("Unsupported: '{} tagged patterns"); }
| yP_DOTSTAR { $$ = NULL; $1->v3error("Unsupported: '{} tagged patterns"); }
@ -3695,6 +3720,10 @@ expr<nodep>: // IEEE: part of expression/constant_expression/primary
| ~l~expr '*' ~r~expr { $$ = new AstMul ($2,$1,$3); }
| ~l~expr '/' ~r~expr { $$ = new AstDiv ($2,$1,$3); }
| ~l~expr '%' ~r~expr { $$ = new AstModDiv ($2,$1,$3); }
| type_reference yP_EQUAL type_reference { $$ = new AstEqT ($2,$1,$3); }
| type_reference yP_NOTEQUAL type_reference { $$ = new AstNeqT ($2,$1,$3); }
| type_reference yP_CASEEQUAL type_reference { $$ = new AstEqT ($2,$1,$3); }
| type_reference yP_CASENOTEQUAL type_reference { $$ = new AstNeqT ($2,$1,$3); }
| ~l~expr yP_EQUAL ~r~expr { $$ = new AstEq ($2,$1,$3); }
| ~l~expr yP_NOTEQUAL ~r~expr { $$ = new AstNeq ($2,$1,$3); }
| ~l~expr yP_CASEEQUAL ~r~expr { $$ = new AstEqCase ($2,$1,$3); }

View File

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

View File

@ -0,0 +1,191 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2020 by Todd Strader.
module foo
#(parameter type a_type = logic,
parameter type b_type = int)
();
initial begin
if (type(a_type) != type(logic[7:0])) begin
$display("%%Error: a_type is wrong");
$stop();
end
if (type(b_type) != type(real)) begin
$display("%%Error: b_type is wrong");
$stop();
end
if (type(a_type) == type(logic)) begin
$display("%%Error: a_type is the default value");
$stop();
end
if (type(b_type) == type(int)) begin
$display("%%Error: b_type is the default value");
$stop();
end
if (type(a_type) == type(b_type)) begin
$display("%%Error: a_type equals b_type");
$stop();
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
package pkg;
typedef struct packed {logic foo;} struct_t;
typedef enum {A_VAL, B_VAL, C_VAL} enum_t;
typedef union packed {
logic [7:0] foo;
logic [3:0] bar;
} union_t;
endpackage
module t();
foo #(
.a_type (logic[7:0]),
.b_type (real)) the_foo ();
shortint shortint_v;
int int_v;
longint longint_v;
byte byte_v;
bit bit_v;
logic logic_v;
reg reg_v;
integer integer_v;
time time_v;
const int int_c;
integer string_to_integer_1[string];
integer string_to_integer_2[string];
integer int_to_integer[int];
int dyn_1 [];
int dyn_2 [];
real dyn_3 [];
int dyn_4 [] [];
int dyn_5 [] [];
int queue_1 [$];
int queue_2 [$];
real queue_3 [$];
// From 6.22.1 (mostly)
typedef bit node; // 'bit' and 'node' are matching types
typedef node type1;
typedef type1 type2; // 'type1' and 'type2' are matching types
struct packed {int A; int B;} AB1, AB2; // AB1, AB2 have matching types
struct packed {int A; int B;} AB3; // the type of AB3 does not match
// the type of AB1
typedef struct packed {int A; int B;} AB_t;
AB_t AB4; AB_t AB5; // AB4 and AB5 have matching types
typedef struct packed {int A; int B;} otherAB_t;
otherAB_t AB6; // the type of AB6 does not match the type of AB4 or AB5
typedef bit signed [7:0] BYTE; // matches the byte type
/* verilator lint_off LITENDIAN */
typedef bit signed [0:7] ETYB; // does not match the byte type
/* verilator lint_on LITENDIAN */
typedef bit [7:0] UNSIGNED_BYTE; // also does not match the byte type
typedef byte MEM_BYTES [256];
typedef bit signed [7:0] MY_MEM_BYTES [256]; // MY_MEM_BYTES matches
// MEM_BYTES
typedef bit signed [7:0] [255:0] MEM_BYTES_PACKED;
typedef bit signed [7:0] [255:0] MY_MEM_BYTES_PACKED;
typedef logic [1:0] [3:0] NIBBLES;
typedef logic [7:0] MY_BYTE; // MY_BYTE and NIBBLES are not matching types
typedef logic MD_ARY [][2:0];
typedef logic MD_ARY_TOO [][0:2]; // Does not match MD_ARY
typedef byte signed MY_CHAR; // MY_CHAR matches the byte type
// 6.22.1 h
import pkg::*;
struct_t struct_v;
enum_t enum_v;
union_t union_v;
bit should_be_true;
initial begin
// size of non-fixed-length arrays does not matter for type matching
string_to_integer_2["foo"] = 5;
dyn_1 = new[100];
dyn_2[3] = 7;
queue_1.push_front(8);
if (type(shortint) != type(shortint_v)) $stop();
if (type(int) != type(int_v)) $stop();
if (type(longint) != type(longint_v)) $stop();
if (type(byte) != type(byte_v)) $stop();
if (type(bit) != type(bit_v)) $stop();
if (type(logic) != type(logic_v)) $stop();
if (type(reg) != type(reg_v)) $stop();
if (type(integer) != type(integer_v)) $stop();
if (type(time) != type(time_v)) $stop();
if (type(string_to_integer_1) != type(string_to_integer_2)) $stop();
if (type(string_to_integer_1) == type(int_to_integer)) $stop();
if (type(dyn_1) != type(dyn_2)) $stop();
if (type(dyn_1) == type(dyn_3)) $stop();
if (type(dyn_1) == type(dyn_4)) $stop();
if (type(dyn_4) != type(dyn_5)) $stop();
if (type(queue_1) != type(queue_2)) $stop();
if (type(queue_1) == type(queue_3)) $stop();
if (type(bit) != type(node)) $stop();
if (type(type1) != type(type2)) $stop();
if (type(AB1) != type(AB2)) $stop();
if (type(AB3) == type(AB1)) $stop();
if (type(AB4) != type(AB5)) $stop();
if (type(AB6) == type(AB4)) $stop();
if (type(AB6) == type(AB5)) $stop();
if (type(BYTE) != type(byte)) $stop();
if (type(ETYB) == type(byte)) $stop();
if (type(BYTE) == type(UNSIGNED_BYTE)) $stop();
if (type(MEM_BYTES) != type(MY_MEM_BYTES)) $stop();
if (type(MEM_BYTES_PACKED) != type(MY_MEM_BYTES_PACKED)) $stop();
if (type(NIBBLES) == type(MY_BYTE)) $stop();
if (type(MD_ARY) == type(MD_ARY_TOO)) $stop();
if (type(MY_CHAR) != type(byte)) $stop();
if (type(struct_v) != type(struct_t)) $stop();
if (type(struct_v) != type(pkg::struct_t)) $stop();
if (type(struct_t) != type(pkg::struct_t)) $stop();
if (type(struct_v.foo) != type(logic)) $stop();
if (type(logic) != type(struct_v.foo)) $stop();
if (type(enum_v) != type(enum_t)) $stop();
if (type(union_v) != type(union_t)) $stop();
// TODO -- the rest
// TODO -- case statement
// TODO -- generate case
if (type(shortint) !== type(shortint_v)) $stop();
if (type(int) === type(shortint_v)) $stop();
if (type(int_c) != type(int_v)) $stop();
if (type(int_v) != type(int_c)) $stop();
should_be_true = '0;
// case (type(shortint_v))
// type(shortint): should_be_true = '1;
// type(int): $stop();
// default: $stop();
// endcase
//
// if (!should_be_true) $stop();
end
endmodule