forked from github/verilator
Support string.toupper and string.tolower.
This commit is contained in:
parent
d480c2f033
commit
0c0198cf55
2
Changes
2
Changes
@ -6,6 +6,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
*** Add +verilator+error+limit to see more assertion errors. [Peter Monsson]
|
||||
|
||||
*** Support string.toupper and string.tolower.
|
||||
|
||||
*** Support $rewind and $ungetc.
|
||||
|
||||
**** Add -Wpedantic for compliance testing.
|
||||
|
@ -1754,7 +1754,22 @@ const char* vl_mc_scan_plusargs(const char* prefixp) VL_MT_SAFE {
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Heavy functions
|
||||
// Heavy string functions
|
||||
|
||||
std::string VL_TOLOWER_NN(const std::string& ld) VL_MT_SAFE {
|
||||
std::string out = ld;
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
|
||||
*it = tolower(*it);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
std::string VL_TOUPPER_NN(const std::string& ld) VL_MT_SAFE {
|
||||
std::string out = ld;
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
|
||||
*it = toupper(*it);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string VL_CVT_PACK_STR_NW(int lwords, WDataInP lwp) VL_MT_SAFE {
|
||||
// See also _VL_VINT_TO_STRING
|
||||
|
@ -61,6 +61,8 @@ inline std::string VL_REPLICATEN_NNI(int obits,int lbits,int rbits,
|
||||
}
|
||||
|
||||
inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
|
||||
extern std::string VL_TOLOWER_NN(const std::string& ld);
|
||||
extern std::string VL_TOUPPER_NN(const std::string& ld);
|
||||
|
||||
extern IData VL_FOPEN_NI(const std::string& filename, IData mode) VL_MT_SAFE;
|
||||
extern void VL_READMEM_N(bool hex, int width, int depth, int array_lsb,
|
||||
|
@ -4532,6 +4532,32 @@ public:
|
||||
virtual string emitVerilog() { return "%f$atanh(%l)"; }
|
||||
virtual string emitC() { return "atanh(%li)"; }
|
||||
};
|
||||
class AstToLowerN : public AstNodeUniop {
|
||||
// string.tolower()
|
||||
public:
|
||||
AstToLowerN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetString(); }
|
||||
ASTNODE_NODE_FUNCS(ToLowerN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToLowerN(lhs); }
|
||||
virtual string emitVerilog() { return "%l.tolower()"; }
|
||||
virtual string emitC() { return "VL_TOLOWER_NN(%li)"; }
|
||||
virtual bool cleanOut() const { return true; }
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
};
|
||||
class AstToUpperN : public AstNodeUniop {
|
||||
// string.toupper()
|
||||
public:
|
||||
AstToUpperN(FileLine* fl, AstNode* lhsp) : AstNodeUniop(fl, lhsp) {
|
||||
dtypeSetString(); }
|
||||
ASTNODE_NODE_FUNCS(ToUpperN)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToUpperN(lhs); }
|
||||
virtual string emitVerilog() { return "%l.toupper()"; }
|
||||
virtual string emitC() { return "VL_TOUPPER_NN(%li)"; }
|
||||
virtual bool cleanOut() const { return true; }
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
// Binary ops
|
||||
|
@ -2074,6 +2074,25 @@ V3Number& V3Number::opReplN(const V3Number& lhs, uint32_t rhsval) {
|
||||
}
|
||||
return setString(out);
|
||||
}
|
||||
V3Number& V3Number::opToLowerN(const V3Number& lhs) {
|
||||
NUM_ASSERT_OP_ARGS1(lhs);
|
||||
NUM_ASSERT_STRING_ARGS1(lhs);
|
||||
std::string out = lhs.toString();
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
|
||||
*it = tolower(*it);
|
||||
}
|
||||
return setString(out);
|
||||
}
|
||||
V3Number& V3Number::opToUpperN(const V3Number& lhs) {
|
||||
NUM_ASSERT_OP_ARGS1(lhs);
|
||||
NUM_ASSERT_STRING_ARGS1(lhs);
|
||||
std::string out = lhs.toString();
|
||||
for (std::string::iterator it = out.begin(); it != out.end(); ++it) {
|
||||
*it = toupper(*it);
|
||||
}
|
||||
return setString(out);
|
||||
}
|
||||
|
||||
V3Number& V3Number::opEqN(const V3Number& lhs, const V3Number& rhs) {
|
||||
NUM_ASSERT_OP_ARGS2(lhs, rhs);
|
||||
NUM_ASSERT_STRING_ARGS2(lhs, rhs);
|
||||
|
@ -288,6 +288,8 @@ public:
|
||||
V3Number& opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval);
|
||||
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
|
||||
V3Number& opSelInto (const V3Number& lhs, int lsbval, int width);
|
||||
V3Number& opToLowerN(const V3Number& lhs);
|
||||
V3Number& opToUpperN(const V3Number& lhs);
|
||||
V3Number& opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s);
|
||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||
|
@ -442,6 +442,18 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstToLowerN* nodep) {
|
||||
if (m_vup->prelim()) {
|
||||
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
|
||||
nodep->dtypeSetString();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstToUpperN* nodep) {
|
||||
if (m_vup->prelim()) {
|
||||
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
|
||||
nodep->dtypeSetString();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstReplicate* nodep) {
|
||||
// IEEE-2012 Table 11-21:
|
||||
// LHS, RHS is self-determined
|
||||
@ -1804,8 +1816,26 @@ private:
|
||||
} else if (nodep->name() == "realtoa") {
|
||||
methodOkArguments(nodep, 1, 1);
|
||||
replaceWithSFormat(nodep, "%g"); VL_DANGLING(nodep);
|
||||
} else {
|
||||
} else if (nodep->name() == "tolower") {
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
AstNode* newp = new AstToLowerN(nodep->fileline(), nodep->fromp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "toupper") {
|
||||
methodOkArguments(nodep, 0, 0);
|
||||
AstNode* newp = new AstToUpperN(nodep->fileline(), nodep->fromp()->unlinkFrBack());
|
||||
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
|
||||
} else if (nodep->name() == "atobin"
|
||||
|| nodep->name() == "atohex"
|
||||
|| nodep->name() == "atoi"
|
||||
|| nodep->name() == "atooct"
|
||||
|| nodep->name() == "atoreal"
|
||||
|| nodep->name() == "compare"
|
||||
|| nodep->name() == "icompare"
|
||||
|| nodep->name() == "getc"
|
||||
|| nodep->name() == "putc") {
|
||||
nodep->v3error("Unsupported: built-in string method "<<nodep->prettyNameQ());
|
||||
} else {
|
||||
nodep->v3error("Unknown built-in string method "<<nodep->prettyNameQ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,11 @@ module t (/*AUTOARG*/
|
||||
// Check constification
|
||||
initial begin
|
||||
s="1234"; `checkh(s.len(),4);
|
||||
s="ab7CD"; `checks(s.toupper(), "AB7CD");
|
||||
s="ab7CD"; `checks(s.tolower(), "ab7cd");
|
||||
`ifndef VERILATOR
|
||||
s="1234"; s.putc(2, "z"); `checks(s, "12z4");
|
||||
s="1234"; `checkh(s.getc(2), "3");
|
||||
s="abCD"; `checks(s.toupper(), "ABCD");
|
||||
s="abCD"; `checks(s.tolower(), "abcd");
|
||||
s="b"; if (s.compare("a") <= 0) $stop;
|
||||
s="b"; if (s.compare("b") != 0) $stop;
|
||||
s="b"; if (s.compare("c") >= 0) $stop;
|
||||
@ -42,6 +42,9 @@ module t (/*AUTOARG*/
|
||||
s.octtoa(123); `checks(s, "173");
|
||||
s.bintoa(123); `checks(s, "1111011");
|
||||
s.realtoa(1.23); `checks(s, "1.23");
|
||||
s = "bAr";
|
||||
s = s.toupper; `checks(s, "BAR");
|
||||
s = s.tolower; `checks(s, "bar");
|
||||
end
|
||||
|
||||
// Check runtime
|
||||
@ -54,40 +57,48 @@ module t (/*AUTOARG*/
|
||||
else if (cyc==1) begin
|
||||
`checkh(s.len(),4);
|
||||
end
|
||||
`ifndef VERILATOR
|
||||
else if (cyc==2) begin
|
||||
`ifndef VERILATOR
|
||||
s.putc(2, "z");
|
||||
`endif
|
||||
end
|
||||
else if (cyc==3) begin
|
||||
`ifndef VERILATOR
|
||||
`checks(s, "12z4");
|
||||
`checkh(s.getc(2), "z");
|
||||
s="abCD";
|
||||
`endif
|
||||
s="ab3CD";
|
||||
end
|
||||
else if (cyc==4) begin
|
||||
`checks(s.toupper(), "ABCD");
|
||||
`checks(s.tolower(), "abcd");
|
||||
`checks(s.toupper(), "AB3CD");
|
||||
`checks(s.tolower(), "ab3cd");
|
||||
s="b";
|
||||
end
|
||||
else if (cyc==5) begin
|
||||
`ifndef VERILATOR
|
||||
if (s.compare("a") <= 0) $stop;
|
||||
if (s.compare("b") != 0) $stop;
|
||||
if (s.compare("c") >= 0) $stop;
|
||||
if (s.icompare("A") < 0) $stop;
|
||||
if (s.icompare("B") != 0) $stop;
|
||||
if (s.icompare("C") >= 0) $stop;
|
||||
`endif
|
||||
s="101";
|
||||
end
|
||||
else if (cyc==7) begin
|
||||
`ifndef VERILATOR
|
||||
`checkh(s.atoi(), 'd101);
|
||||
`checkh(s.atohex(), 'h101);
|
||||
`checkh(s.atooct(), 'o101);
|
||||
`checkh(s.atobin(), 'b101);
|
||||
`endif
|
||||
s="1.23";
|
||||
end
|
||||
else if (cyc==8) begin
|
||||
`ifndef VERILATOR
|
||||
`checkg(s.atoreal(), 1.23);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
else if (cyc==9) begin
|
||||
s.itoa(123);
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user