Support pattern assignment to dynamic arrays.

This commit is contained in:
Wilson Snyder 2020-11-01 10:18:32 -05:00
parent 1858cc8ff1
commit c1e8337fc1
4 changed files with 117 additions and 15 deletions

View File

@ -4668,6 +4668,28 @@ public:
virtual bool same(const AstNode* samep) const override { return true; }
};
class AstConsDynArray : public AstNodeMath {
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
// Parents: math
// Children: expression (elements or other queues)
public:
AstConsDynArray(FileLine* fl, AstNode* lhsp = nullptr, AstNode* rhsp = nullptr)
: ASTGEN_SUPER(fl) {
setNOp1p(lhsp);
setNOp2p(rhsp);
}
ASTNODE_NODE_FUNCS(ConsDynArray)
virtual string emitVerilog() override { return "'{%l, %r}"; }
virtual string emitC() override { V3ERROR_NA_RETURN(""); }
virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); }
virtual bool cleanOut() const override { return true; }
virtual int instrCount() const override { return widthInstrs(); }
AstNode* lhsp() const { return op1p(); } // op1 = expression
AstNode* rhsp() const { return op2p(); } // op2 = expression
virtual V3Hash sameHash() const override { return V3Hash(); }
virtual bool same(const AstNode* samep) const override { return true; }
};
class AstConsQueue : public AstNodeMath {
// Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs}
// Parents: math

View File

@ -1593,6 +1593,21 @@ class EmitCImp : EmitCStmts {
iterateAndNextNull(nodep->valuep());
puts(")");
}
virtual void visit(AstConsDynArray* nodep) override {
putbs(nodep->dtypep()->cType("", false, false));
if (!nodep->lhsp()) {
puts("()");
} else {
puts("::cons(");
iterateAndNextNull(nodep->lhsp());
if (nodep->rhsp()) {
puts(", ");
putbs("");
}
iterateAndNextNull(nodep->rhsp());
puts(")");
}
}
virtual void visit(AstConsQueue* nodep) override {
putbs(nodep->dtypep()->cType("", false, false));
if (!nodep->lhsp()) {

View File

@ -485,6 +485,7 @@ private:
// signed: Unsigned (11.8.1)
// width: LHS + RHS
AstNodeDType* vdtypep = m_vup->dtypeNullSkipRefp();
userIterateAndNext(vdtypep, WidthVP(SELF, BOTH).p());
if (VN_IS(vdtypep, QueueDType)) {
// Queue "element 0" is lhsp, so we need to swap arguments
auto* newp = new AstConsQueue(nodep->fileline(), nodep->rhsp()->unlinkFrBack(),
@ -494,6 +495,14 @@ private:
userIterateChildren(newp, m_vup);
return;
}
if (VN_IS(vdtypep, DynArrayDType)) {
auto* newp = new AstConsDynArray(nodep->fileline(), nodep->rhsp()->unlinkFrBack(),
nodep->lhsp()->unlinkFrBack());
nodep->replaceWith(newp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
userIterateChildren(newp, m_vup);
return;
}
if (m_vup->prelim()) {
if (VN_IS(vdtypep, AssocArrayDType) //
|| VN_IS(vdtypep, DynArrayDType) //
@ -633,7 +642,7 @@ private:
}
AstNodeDType* vdtypep = m_vup->dtypeNullSkipRefp();
if (VN_IS(vdtypep, QueueDType)) {
if (VN_IS(vdtypep, QueueDType) || VN_IS(vdtypep, DynArrayDType)) {
if (times != 1)
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Non-1 replication to form "
<< vdtypep->prettyDTypeNameQ()
@ -645,8 +654,7 @@ private:
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return;
}
if (VN_IS(vdtypep, AssocArrayDType) || VN_IS(vdtypep, DynArrayDType)
|| VN_IS(vdtypep, UnpackArrayDType)) {
if (VN_IS(vdtypep, AssocArrayDType) || VN_IS(vdtypep, UnpackArrayDType)) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Replication to form "
<< vdtypep->prettyDTypeNameQ() << " data type");
}
@ -1509,6 +1517,11 @@ private:
}
UINFO(4, "dtWidthed " << nodep << endl);
}
virtual void visit(AstVoidDType* nodep) override {
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
nodep->dtypep(nodep);
UINFO(4, "dtWidthed " << nodep << endl);
}
virtual void visit(AstUnsizedArrayDType* nodep) override {
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed
// Iterate into subDTypep() to resolve that type and update pointer.
@ -1985,6 +1998,38 @@ private:
EXTEND_EXP);
}
}
virtual void visit(AstConsDynArray* nodep) override {
// Type computed when constructed here
AstDynArrayDType* vdtypep = VN_CAST(m_vup->dtypep(), DynArrayDType);
UASSERT_OBJ(vdtypep, nodep, "ConsDynArray requires queue upper parent data type");
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, PRELIM).p());
userIterateAndNext(nodep->rhsp(), WidthVP(vdtypep, PRELIM).p());
nodep->dtypeFrom(vdtypep);
}
if (m_vup->final()) {
// Arguments can be either elements of the queue or a queue itself
// Concats (part of tree of concats) must always become ConsDynArray's
if (nodep->lhsp()) {
if (VN_IS(nodep->lhsp()->dtypep(), DynArrayDType)
|| VN_IS(nodep->lhsp(), ConsDynArray)) {
userIterateAndNext(nodep->lhsp(), WidthVP(vdtypep, FINAL).p());
} else {
// Sub elements are not queues, but concats, must always pass concats down
iterateCheckTyped(nodep, "LHS", nodep->lhsp(), vdtypep->subDTypep(), FINAL);
}
}
if (nodep->rhsp()) {
if (VN_IS(nodep->rhsp()->dtypep(), DynArrayDType)
|| VN_IS(nodep->rhsp(), ConsDynArray)) {
userIterateAndNext(nodep->rhsp(), WidthVP(vdtypep, FINAL).p());
} else {
iterateCheckTyped(nodep, "RHS", nodep->rhsp(), vdtypep->subDTypep(), FINAL);
}
}
nodep->dtypeFrom(vdtypep);
}
}
virtual void visit(AstConsQueue* nodep) override {
// Type computed when constructed here
AstQueueDType* vdtypep = VN_CAST(m_vup->dtypep(), QueueDType);
@ -2969,12 +3014,15 @@ private:
while (const AstConstDType* vdtypep = VN_CAST(dtypep, ConstDType)) {
dtypep = vdtypep->subDTypep()->skipRefp();
}
userIterateAndNext(dtypep, WidthVP(SELF, BOTH).p());
if (auto* vdtypep = VN_CAST(dtypep, NodeUOrStructDType)) {
VL_DO_DANGLING(patternUOrStruct(nodep, vdtypep, defaultp), nodep);
} else if (auto* vdtypep = VN_CAST(dtypep, NodeArrayDType)) {
VL_DO_DANGLING(patternArray(nodep, vdtypep, defaultp), nodep);
} else if (auto* vdtypep = VN_CAST(dtypep, AssocArrayDType)) {
VL_DO_DANGLING(patternAssoc(nodep, vdtypep, defaultp), nodep);
} else if (auto* vdtypep = VN_CAST(dtypep, DynArrayDType)) {
VL_DO_DANGLING(patternDynArray(nodep, vdtypep, defaultp), nodep);
} else if (auto* vdtypep = VN_CAST(dtypep, QueueDType)) {
VL_DO_DANGLING(patternQueue(nodep, vdtypep, defaultp), nodep);
} else if (VN_IS(dtypep, BasicDType) && VN_CAST(dtypep, BasicDType)->isRanged()) {
@ -3155,6 +3203,21 @@ private:
// if (debug() >= 9) newp->dumpTree("-apat-out: ");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
}
void patternDynArray(AstPattern* nodep, AstDynArrayDType* arrayp, AstPatMember* defaultp) {
AstNode* newp = new AstConsDynArray(nodep->fileline());
newp->dtypeFrom(arrayp);
for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp;
patp = VN_CAST(patp->nextp(), PatMember)) {
patp->dtypep(arrayp->subDTypep());
AstNode* valuep = patternMemberValueIterate(patp);
auto* newap = new AstConsDynArray(nodep->fileline(), valuep, newp);
newap->dtypeFrom(arrayp);
newp = newap;
}
nodep->replaceWith(newp);
// if (debug() >= 9) newp->dumpTree("-apat-out: ");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
}
void patternQueue(AstPattern* nodep, AstQueueDType* arrayp, AstPatMember* defaultp) {
AstNode* newp = new AstConsQueue(nodep->fileline());
newp->dtypeFrom(arrayp);

View File

@ -36,12 +36,19 @@ module t (/*AUTOARG*/
pck256_t p256[];
string s[] = { "hello", "sad", "world" };
always @ (posedge clk) begin
cyc <= cyc + 1;
begin
`checkh(a.size, 0);
v = $sformatf("%p", a); `checks(v, "'{}");
`checkh(s.size, 3);
`checks(s[0], "hello");
`checks(s[1], "sad");
`checks(s[2], "world");
a = new [3];
`checkh(a.size, 3);
a[0] = 10;
@ -54,22 +61,17 @@ module t (/*AUTOARG*/
a.delete;
`checkh(a.size, 0);
a = new [2];
`ifdef verilator // Unsupported pattern assignment
a[0] = 15; a[1] = 16;
`else
a = '{15, 16};
`endif
`checkh(a.size, 2);
`checkh(a[0], 15);
`checkh(a[1], 16)
`ifdef verilator // Unsupported pattern assignment
a = new [1];
a[0] = 17;
`else
a = {17, 18};
`checkh(a.size, 2);
`checkh(a[0], 17);
`checkh(a[1], 18)
a = '{17};
`endif
`checkh(a.size, 1); // IEEE says resizes to smallest that fits pattern
`checkh(a[0], 17);
@ -122,7 +124,7 @@ module t (/*AUTOARG*/
`checkh(b[0], 0);
`checkh(b[1], 0);
`checkh(b[2], 0);
`checkh(b[4], 0);
`checkh(b[3], 0);
// test wide dynamic array
p256 = new [11];
@ -135,7 +137,7 @@ module t (/*AUTOARG*/
`checkh(p256[1].header, 16'hcafe);
`checkh(p256[1], {16'hcafe,{14{16'hbabe}},16'hdead});
`checkh(p256[0], '0);
//X's: `checkh(p256[0], 'x);
p256[5] = '1;
`checkh(p256[5], {32{8'hff}});