Support pattern assignment to dynamic arrays.
This commit is contained in:
parent
1858cc8ff1
commit
c1e8337fc1
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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}});
|
||||
|
|
|
|||
Loading…
Reference in New Issue