forked from github/verilator
Support string character access via indexing.
This commit is contained in:
parent
5430e4ac9b
commit
9fd81b2c6b
2
Changes
2
Changes
@ -19,6 +19,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
**** Support left justified $display, #2101. [Pieter Kapsenberg]
|
||||
|
||||
**** Support string character access via indexing.
|
||||
|
||||
**** Add parameter values in XML. #2110. [Pieter Kapsenberg]
|
||||
|
||||
**** Add loc column location in XML (replaces fl), #2122. [Pieter Kapsenberg]
|
||||
|
@ -6188,6 +6188,29 @@ public:
|
||||
virtual bool sizeMattersRhs() const { return false; }
|
||||
};
|
||||
|
||||
class AstGetcRefN : public AstNodeBiop {
|
||||
// Verilog string[#] on the left-hand-side of assignment
|
||||
// Spec says is of type byte (not string of single character)
|
||||
public:
|
||||
AstGetcRefN(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
||||
: ASTGEN_SUPER(fl, lhsp, rhsp) { dtypeSetBitSized(8, AstNumeric::UNSIGNED); }
|
||||
ASTNODE_NODE_FUNCS(GetcRefN)
|
||||
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) {
|
||||
return new AstGetcRefN(this->fileline(), lhsp, rhsp);
|
||||
}
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) {
|
||||
V3ERROR_NA;
|
||||
}
|
||||
virtual string emitVerilog() { return "%k%l[%r]"; }
|
||||
virtual string emitC() { V3ERROR_NA; }
|
||||
virtual string emitSimpleOperator() { return ""; }
|
||||
virtual bool cleanOut() const { return true; }
|
||||
virtual bool cleanLhs() const { return true; }
|
||||
virtual bool cleanRhs() const { return true; }
|
||||
virtual bool sizeMattersLhs() const { return false; }
|
||||
virtual bool sizeMattersRhs() const { return false; }
|
||||
};
|
||||
|
||||
class AstSubstrN : public AstNodeTriop {
|
||||
// Verilog string.substr()
|
||||
public:
|
||||
|
@ -229,6 +229,14 @@ public:
|
||||
iterateAndNextNull(selp->lsbp()); puts(", ");
|
||||
iterateAndNextNull(selp->fromp()); puts(", ");
|
||||
}
|
||||
} else if (AstGetcRefN* selp = VN_CAST(nodep->lhsp(), GetcRefN)) {
|
||||
iterateAndNextNull(selp->lhsp());
|
||||
puts(" = ");
|
||||
putbs("VL_PUTC_N(");
|
||||
iterateAndNextNull(selp->lhsp());
|
||||
puts(", ");
|
||||
iterateAndNextNull(selp->rhsp());
|
||||
puts(", ");
|
||||
} else if (AstVar* varp = AstVar::scVarRecurse(nodep->lhsp())) {
|
||||
putbs("VL_ASSIGN_"); // Set a systemC variable
|
||||
emitScIQW(varp);
|
||||
|
@ -74,6 +74,10 @@ class EmitCInlines : EmitCBaseVisitor {
|
||||
v3Global.needHeavy(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstGetcRefN* nodep) VL_OVERRIDE {
|
||||
v3Global.needHeavy(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstSubstrN* nodep) VL_OVERRIDE {
|
||||
v3Global.needHeavy(true);
|
||||
iterateChildren(nodep);
|
||||
|
@ -355,6 +355,16 @@ private:
|
||||
nodep->dtypeSetBitSized(8, AstNumeric::UNSIGNED);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstGetcRefN* nodep) VL_OVERRIDE {
|
||||
// CALLER: str.getc()
|
||||
UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!");
|
||||
if (m_vup && m_vup->prelim()) {
|
||||
// See similar handling in visit_cmp_eq_gt where created
|
||||
iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH);
|
||||
iterateCheckSigned32(nodep, "RHS", nodep->rhsp(), BOTH);
|
||||
nodep->dtypeSetBitSized(8, AstNumeric::UNSIGNED);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSubstrN* nodep) VL_OVERRIDE {
|
||||
// CALLER: str.substr()
|
||||
UASSERT_OBJ(nodep->rhsp() && nodep->thsp(), nodep, "For ternary ops only!");
|
||||
|
@ -99,7 +99,8 @@ private:
|
||||
fromRange = adtypep->declRange();
|
||||
}
|
||||
else if (AstBasicDType* adtypep = VN_CAST(ddtypep, BasicDType)) {
|
||||
if (adtypep->isRanged()) {
|
||||
if (adtypep->isString() && VN_IS(nodep, SelBit)) {
|
||||
} else if (adtypep->isRanged()) {
|
||||
UASSERT_OBJ(!(adtypep->rangep()
|
||||
&& (!VN_IS(adtypep->rangep()->msbp(), Const)
|
||||
|| !VN_IS(adtypep->rangep()->lsbp(), Const))),
|
||||
@ -268,7 +269,20 @@ private:
|
||||
if (debug()>=9) newp->dumpTree(cout, "--SELBTq: ");
|
||||
nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
else if (VN_IS(ddtypep, BasicDType)) {
|
||||
else if (VN_IS(ddtypep, BasicDType) && ddtypep->isString()) {
|
||||
// SELBIT(string, index) -> GETC(string, index)
|
||||
AstNodeVarRef* varrefp = VN_CAST(fromp, NodeVarRef);
|
||||
if (!varrefp) nodep->v3error("Unsupported: String array operation on non-variable");
|
||||
AstNode* newp;
|
||||
if (varrefp && varrefp->lvalue()) {
|
||||
newp = new AstGetcRefN(nodep->fileline(), fromp, rhsp);
|
||||
} else {
|
||||
newp = new AstGetcN(nodep->fileline(), fromp, rhsp);
|
||||
}
|
||||
UINFO(6, " new " << newp << endl);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else if (VN_IS(ddtypep, BasicDType)) {
|
||||
// SELBIT(range, index) -> SEL(array, index, 1)
|
||||
AstSel* newp = new AstSel(nodep->fileline(),
|
||||
fromp,
|
||||
|
@ -4,7 +4,7 @@
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
|
||||
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checks(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=\"%s\" exp=\"%s\"\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=\"%s\" exp=\"%s\"\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
@ -98,6 +98,19 @@ module t (/*AUTOARG*/
|
||||
`checkh(s <= " ", 1'b0);
|
||||
`checkh(s <= "a", 1'b1);
|
||||
end
|
||||
// String character references
|
||||
else if (cyc==10) begin
|
||||
s2 = "astring";
|
||||
end
|
||||
else if (cyc==11) begin
|
||||
`checks(s2, "astring");
|
||||
`checkh(s2.len(), 7);
|
||||
`checkh(s2[1], "s");
|
||||
s2[0] = "0";
|
||||
s2[3] = "3";
|
||||
`checks(s2, "0st3ing");
|
||||
end
|
||||
//
|
||||
else if (cyc==99) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
|
Loading…
Reference in New Issue
Block a user