Support string character access via indexing.

This commit is contained in:
Wilson Snyder 2020-01-26 16:38:22 -05:00
parent 5430e4ac9b
commit 9fd81b2c6b
7 changed files with 77 additions and 3 deletions

View File

@ -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]

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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!");

View File

@ -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,

View File

@ -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;