mirror of
https://github.com/verilator/verilator.git
synced 2026-10-08 02:53:12 +02:00
Support string len() method.
This commit is contained in:
@@ -3545,6 +3545,18 @@ public:
|
||||
virtual int instrCount() const { return 1+V3Number::log2b(width()); }
|
||||
};
|
||||
|
||||
class AstLenN : public AstNodeUniop {
|
||||
// Length of a string
|
||||
public:
|
||||
AstLenN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetSigned32(); }
|
||||
ASTNODE_NODE_FUNCS(LenN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); }
|
||||
virtual string emitVerilog() { return "%f(%l)"; }
|
||||
virtual string emitC() { return "VL_LEN_IN(%li)"; }
|
||||
virtual bool cleanOut() {return true;} virtual bool cleanLhs() {return true;}
|
||||
virtual bool sizeMattersLhs() {return false;}
|
||||
};
|
||||
class AstLogNot : public AstNodeUniop {
|
||||
public:
|
||||
AstLogNot(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
|
||||
@@ -1035,6 +1035,11 @@ V3Number& V3Number::opConcat (const V3Number& lhs, const V3Number& rhs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opLenN (const V3Number& lhs) {
|
||||
setQuad(lhs.toString().length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
V3Number& V3Number::opRepl (const V3Number& lhs, const V3Number& rhs) { // rhs is # of times to replicate
|
||||
// Hopefully the using routine has a error check too.
|
||||
// See also error in V3Width
|
||||
|
||||
@@ -242,6 +242,7 @@ public:
|
||||
V3Number& opCLog2 (const V3Number& lhs);
|
||||
V3Number& opClean (const V3Number& lhs, uint32_t bits);
|
||||
V3Number& opConcat (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opLenN (const V3Number& lhs);
|
||||
V3Number& opRepl (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opRepl (const V3Number& lhs, uint32_t rhs);
|
||||
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
||||
|
||||
@@ -330,6 +330,9 @@ private:
|
||||
// Widths: Output integer unsigned, input real
|
||||
virtual void visit(AstRealToBits* nodep) { visit_Ou64_Lr(nodep); }
|
||||
|
||||
// Output integer, input string
|
||||
virtual void visit(AstLenN* nodep) { visit_Os32_string(nodep); }
|
||||
|
||||
// Widths: Constant, terminal
|
||||
virtual void visit(AstTime* nodep) { nodep->dtypeSetUInt64(); }
|
||||
virtual void visit(AstTimeD* nodep) { nodep->dtypeSetDouble(); }
|
||||
@@ -1497,6 +1500,7 @@ private:
|
||||
// Find the fromp dtype - should be a class
|
||||
if (!nodep->fromp() || !nodep->fromp()->dtypep()) nodep->v3fatalSrc("Unsized expression");
|
||||
AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump();
|
||||
AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL;
|
||||
UINFO(9," from dt "<<fromDtp<<endl);
|
||||
if (AstEnumDType* adtypep = fromDtp->castEnumDType()) {
|
||||
// Method call on enum without following parenthesis, e.g. "ENUM.next"
|
||||
@@ -1613,6 +1617,17 @@ private:
|
||||
nodep->v3error("Unknown built-in array method '"<<nodep->fromp()->prettyTypeName()<<"'");
|
||||
}
|
||||
}
|
||||
else if (basicp && basicp->isString()) {
|
||||
// Method call on string
|
||||
if (nodep->name() == "len") {
|
||||
// Constant value
|
||||
AstNode* newp = new AstLenN(nodep->fileline(), nodep->fromp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp);
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
} else {
|
||||
nodep->v3error("Unsupported: built-in string method '"<<nodep->fromp()->prettyTypeName()<<"'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
nodep->v3error("Unsupported: Member call on non-enum object '"
|
||||
<<nodep->fromp()->prettyTypeName()<<"' which is a '"<<nodep->fromp()->dtypep()->prettyTypeName()<<"'");
|
||||
@@ -2646,6 +2661,16 @@ private:
|
||||
nodep->dtypeSetLogicBool();
|
||||
}
|
||||
}
|
||||
void visit_Os32_string(AstNodeUniop* nodep) {
|
||||
// CALLER: LenN
|
||||
// Widths: 32 bit out
|
||||
if (!nodep->lhsp()) nodep->v3fatalSrc("For unary ops only!");
|
||||
if (m_vup->prelim()) {
|
||||
// See similar handling in visit_cmp_eq_gt where created
|
||||
iterateCheckString(nodep,"LHS",nodep->lhsp(),BOTH);
|
||||
nodep->dtypeSetSigned32();
|
||||
}
|
||||
}
|
||||
|
||||
void visit_negate_not(AstNodeUniop* nodep, bool real_ok) {
|
||||
// CALLER: (real_ok=false) Not
|
||||
|
||||
Reference in New Issue
Block a user