mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Merge branch 'master' into develop-v5
This commit is contained in:
+3
-1
@@ -6127,7 +6127,9 @@ public:
|
||||
class AstCLog2 final : public AstNodeUniop {
|
||||
public:
|
||||
AstCLog2(FileLine* fl, AstNode* lhsp)
|
||||
: ASTGEN_SUPER_CLog2(fl, lhsp) {}
|
||||
: ASTGEN_SUPER_CLog2(fl, lhsp) {
|
||||
dtypeSetSigned32();
|
||||
}
|
||||
ASTNODE_NODE_FUNCS(CLog2)
|
||||
virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); }
|
||||
virtual string emitVerilog() override { return "%f$clog2(%l)"; }
|
||||
|
||||
+30
-16
@@ -566,9 +566,35 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
||||
const AstConst* const constp = VN_CAST(lhsp, Const);
|
||||
CONST_BITOP_RETURN_IF(!constp, nodep->lhsp());
|
||||
|
||||
const bool maskFlip = isOrTree();
|
||||
const V3Number& compNum = constp->num();
|
||||
|
||||
auto setPolarities = [this, &compNum](const LeafInfo& ref, const V3Number* maskp) {
|
||||
const bool maskFlip = isOrTree();
|
||||
int constantWidth = compNum.width();
|
||||
if (maskp) constantWidth = std::max(constantWidth, maskp->width());
|
||||
const int maxBitIdx = std::max(ref.lsb() + constantWidth, ref.msb() + 1);
|
||||
// Mark all bits checked by this comparison
|
||||
for (int bitIdx = ref.lsb(); bitIdx < maxBitIdx; ++bitIdx) {
|
||||
const int maskIdx = bitIdx - ref.lsb();
|
||||
const bool mask0 = maskp && maskp->bitIs0(maskIdx);
|
||||
const bool outOfRange = bitIdx > ref.msb();
|
||||
if (mask0 || outOfRange) { // RHS is 0
|
||||
if (compNum.bitIs1(maskIdx)) {
|
||||
// LHS is 1
|
||||
// And tree: 1 == 0 => always false, set v && !v
|
||||
// Or tree : 1 != 0 => always true, set v || !v
|
||||
m_bitPolarities.emplace_back(ref, true, 0);
|
||||
m_bitPolarities.emplace_back(ref, false, 0);
|
||||
break;
|
||||
} else { // This bitIdx is irrelevant
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const bool polarity = compNum.bitIs1(maskIdx) != maskFlip;
|
||||
m_bitPolarities.emplace_back(ref, polarity, bitIdx);
|
||||
}
|
||||
};
|
||||
|
||||
if (const AstAnd* const andp = VN_CAST(nodep->rhsp(), And)) { // comp == (mask & v)
|
||||
const LeafInfo& mask = findLeaf(andp->lhsp(), true);
|
||||
CONST_BITOP_RETURN_IF(!mask.constp() || mask.lsb() != 0, andp->lhsp());
|
||||
@@ -583,14 +609,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
||||
incrOps(nodep, __LINE__);
|
||||
incrOps(andp, __LINE__);
|
||||
|
||||
// Mark all bits checked by this comparison
|
||||
const int maxBitIdx = std::min(ref.lsb() + maskNum.width(), ref.msb() + 1);
|
||||
for (int bitIdx = ref.lsb(); bitIdx < maxBitIdx; ++bitIdx) {
|
||||
const int maskIdx = bitIdx - ref.lsb();
|
||||
if (maskNum.bitIs0(maskIdx)) continue;
|
||||
const bool polarity = compNum.bitIs1(maskIdx) != maskFlip;
|
||||
m_bitPolarities.emplace_back(ref, polarity, bitIdx);
|
||||
}
|
||||
setPolarities(ref, &maskNum);
|
||||
} else { // comp == v
|
||||
const LeafInfo& ref = findLeaf(nodep->rhsp(), false);
|
||||
CONST_BITOP_RETURN_IF(!ref.refp(), nodep->rhsp());
|
||||
@@ -599,13 +618,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
||||
|
||||
incrOps(nodep, __LINE__);
|
||||
|
||||
// Mark all bits checked by this comparison
|
||||
const int maxBitIdx = std::min(ref.lsb() + compNum.width(), ref.msb() + 1);
|
||||
for (int bitIdx = ref.lsb(); bitIdx < maxBitIdx; ++bitIdx) {
|
||||
const int maskIdx = bitIdx - ref.lsb();
|
||||
const bool polarity = compNum.bitIs1(maskIdx) != maskFlip;
|
||||
m_bitPolarities.emplace_back(ref, polarity, bitIdx);
|
||||
}
|
||||
setPolarities(ref, nullptr);
|
||||
}
|
||||
} else {
|
||||
CONST_BITOP_SET_FAILED("Mixture of different ops cannot be optimized", nodep);
|
||||
@@ -1751,6 +1764,7 @@ private:
|
||||
lp->rhsp(lrp);
|
||||
nodep->lhsp(llp);
|
||||
nodep->rhsp(rlp);
|
||||
nodep->dtypep(llp->dtypep()); // dtype of Biop is before shift.
|
||||
VL_DO_DANGLING(rp->deleteTree(), rp);
|
||||
VL_DO_DANGLING(rrp->deleteTree(), rrp);
|
||||
// nodep->dumpTree(cout, " repShiftSame_new: ");
|
||||
|
||||
+1
-1
@@ -247,7 +247,7 @@ public:
|
||||
|
||||
// OPERATORS
|
||||
void v3errorEnd(std::ostringstream& str, const string& extra = "");
|
||||
void v3errorEndFatal(std::ostringstream& str);
|
||||
void v3errorEndFatal(std::ostringstream& str) VL_ATTR_NORETURN;
|
||||
/// When building an error, prefix for printing continuation lines
|
||||
/// e.g. information referring to the same FileLine as before
|
||||
string warnMore() const;
|
||||
|
||||
@@ -790,6 +790,8 @@ private:
|
||||
// otherwise end the current merge. Return ture if added, false if ended merge.
|
||||
bool addIfHelpfulElseEndMerge(AstNodeStmt* nodep) {
|
||||
UASSERT_OBJ(m_mgFirstp, nodep, "List must be open");
|
||||
if (!checkOrMakeMergeable(nodep)) return false;
|
||||
if (!m_mgFirstp) return false; // If 'checkOrMakeMergeable' closed the list
|
||||
if (m_mgNextp == nodep) {
|
||||
if (isSimplifiableNode(nodep)) {
|
||||
if (addToList(nodep, nullptr)) return true;
|
||||
|
||||
+2
-2
@@ -1010,11 +1010,11 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
|
||||
if (!strcmp(valp, "clang")) {
|
||||
m_compLimitBlocks = 80; // limit unknown
|
||||
m_compLimitMembers = 64; // soft limit, has slowdown bug as of clang++ 3.8
|
||||
m_compLimitParens = 80; // limit unknown
|
||||
m_compLimitParens = 240; // controlled by -fbracket-depth, which defaults to 256
|
||||
} else if (!strcmp(valp, "gcc")) {
|
||||
m_compLimitBlocks = 0; // Bug free
|
||||
m_compLimitMembers = 64; // soft limit, has slowdown bug as of g++ 7.1
|
||||
m_compLimitParens = 0; // Bug free
|
||||
m_compLimitParens = 240; // Unlimited, but generate same code as for clang
|
||||
} else if (!strcmp(valp, "msvc")) {
|
||||
m_compLimitBlocks = 80; // 128, but allow some room
|
||||
m_compLimitMembers = 0; // probably ok, and AFAIK doesn't support anon structs
|
||||
|
||||
+1
-1
@@ -315,7 +315,7 @@ private:
|
||||
|
||||
int m_compLimitBlocks = 0; // compiler selection; number of nested blocks
|
||||
int m_compLimitMembers = 64; // compiler selection; number of members in struct before make anon array
|
||||
int m_compLimitParens = 0; // compiler selection; number of nested parens
|
||||
int m_compLimitParens = 240; // compiler selection; number of nested parens
|
||||
|
||||
string m_bin; // main switch: --bin {binary}
|
||||
string m_exeName; // main switch: -o {name}
|
||||
|
||||
+59
-37
@@ -1248,10 +1248,7 @@ private:
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCLog2* nodep) override {
|
||||
if (m_vup->prelim()) {
|
||||
iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH);
|
||||
nodep->dtypeSetSigned32();
|
||||
}
|
||||
if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); }
|
||||
}
|
||||
virtual void visit(AstPow* nodep) override {
|
||||
// Pow is special, output sign only depends on LHS sign, but
|
||||
@@ -3564,50 +3561,66 @@ private:
|
||||
// which member each AstPatMember corresponds to before we can
|
||||
// determine the dtypep for that PatMember's value, and then
|
||||
// width the initial value appropriately.
|
||||
using PatMap = std::map<const AstMemberDType*, AstPatMember*>;
|
||||
using PatMap = std::map<const AstMemberDType*, AstPatMember*>; // Store member: value
|
||||
using DTypeMap
|
||||
= std::map<const std::string, AstPatMember*>; // Store data_type: default_value
|
||||
PatMap patmap;
|
||||
DTypeMap dtypemap;
|
||||
{
|
||||
const AstMemberDType* memp = vdtypep->membersp();
|
||||
AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember);
|
||||
for (; memp || patp;) {
|
||||
while (patp) {
|
||||
do {
|
||||
if (patp) {
|
||||
if (patp->keyp()) {
|
||||
if (const AstText* textp = VN_CAST(patp->keyp(), Text)) {
|
||||
memp = vdtypep->findMember(textp->text());
|
||||
if (!memp) {
|
||||
patp->keyp()->v3error("Assignment pattern key '"
|
||||
<< textp->text()
|
||||
<< "' not found as member");
|
||||
break;
|
||||
}
|
||||
if (patp->keyp()) {
|
||||
// '{member:value} or '{data_type: default_value}
|
||||
if (const AstText* textp = VN_CAST(patp->keyp(), Text)) {
|
||||
// member: value
|
||||
memp = vdtypep->findMember(textp->text());
|
||||
if (!memp) {
|
||||
patp->keyp()->v3error("Assignment pattern key '"
|
||||
<< textp->text() << "' not found as member");
|
||||
break;
|
||||
} else {
|
||||
patp->keyp()->v3error(
|
||||
"Assignment pattern key not supported/understood: "
|
||||
<< patp->keyp()->prettyTypeName());
|
||||
const std::pair<PatMap::iterator, bool> ret
|
||||
= patmap.emplace(memp, patp);
|
||||
if (!ret.second) {
|
||||
patp->v3error("Assignment pattern contains duplicate entry: "
|
||||
<< VN_AS(patp->keyp(), Text)->text());
|
||||
}
|
||||
memp = VN_AS(memp->nextp(), MemberDType);
|
||||
}
|
||||
} else if (const AstNodeDType* nodedtypep
|
||||
= VN_CAST(patp->keyp(), NodeDType)) {
|
||||
// data_type: default_value
|
||||
const string dtype = nodedtypep->dtypep()->prettyDTypeName();
|
||||
auto it = dtypemap.find(dtype);
|
||||
if (it == dtypemap.end()) {
|
||||
dtypemap.emplace(dtype, patp);
|
||||
} else {
|
||||
// Override stored default_value
|
||||
it->second = patp->cloneTree(false);
|
||||
}
|
||||
} else {
|
||||
// Undefined pattern
|
||||
patp->keyp()->v3error(
|
||||
"Assignment pattern key not supported/understood: "
|
||||
<< patp->keyp()->prettyTypeName());
|
||||
}
|
||||
}
|
||||
if (memp && !patp) {
|
||||
// Missing init elements, warn below
|
||||
memp = nullptr;
|
||||
patp = nullptr;
|
||||
break;
|
||||
} else if (!memp && patp) {
|
||||
patp->v3error("Assignment pattern contains too many elements");
|
||||
memp = nullptr;
|
||||
patp = nullptr;
|
||||
break;
|
||||
} else {
|
||||
const std::pair<PatMap::iterator, bool> ret = patmap.emplace(memp, patp);
|
||||
if (!ret.second) {
|
||||
patp->v3error("Assignment pattern contains duplicate entry: "
|
||||
<< VN_AS(patp->keyp(), Text)->text());
|
||||
// constant expr
|
||||
if (memp) {
|
||||
const std::pair<PatMap::iterator, bool> ret
|
||||
= patmap.emplace(memp, patp);
|
||||
if (!ret.second) {
|
||||
patp->v3error("Assignment pattern contains duplicate entry: "
|
||||
<< VN_AS(patp->keyp(), Text)->text());
|
||||
}
|
||||
memp = VN_AS(memp->nextp(), MemberDType);
|
||||
}
|
||||
}
|
||||
} while (false);
|
||||
|
||||
// Next
|
||||
if (memp) memp = VN_AS(memp->nextp(), MemberDType);
|
||||
if (patp) patp = VN_AS(patp->nextp(), PatMember);
|
||||
}
|
||||
}
|
||||
@@ -3618,13 +3631,22 @@ private:
|
||||
AstPatMember* newpatp = nullptr;
|
||||
AstPatMember* patp = nullptr;
|
||||
if (it == patmap.end()) {
|
||||
if (defaultp) {
|
||||
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName();
|
||||
const auto it2 = dtypemap.find(memp_DType);
|
||||
if (it2 != dtypemap.end()) {
|
||||
// default_value for data_type
|
||||
patp = it2->second;
|
||||
newpatp = patp->cloneTree(false);
|
||||
patp = newpatp;
|
||||
} else if (defaultp) {
|
||||
// default_value for any unassigned member yet
|
||||
newpatp = defaultp->cloneTree(false);
|
||||
patp = newpatp;
|
||||
} else {
|
||||
if (!VN_IS(vdtypep, UnionDType)) {
|
||||
nodep->v3error("Assignment pattern missed initializing elements: "
|
||||
<< memp->prettyTypeName());
|
||||
<< memp->virtRefDTypep()->prettyDTypeName() << " "
|
||||
<< memp->prettyName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -3545,6 +3545,7 @@ patternKey<nodep>: // IEEE: merge structure_pattern_key, array_patt
|
||||
| yaFLOATNUM { $$ = new AstConst($<fl>1,AstConst::RealDouble(),$1); }
|
||||
| id { $$ = new AstText($<fl>1,*$1); }
|
||||
| strAsInt { $$ = $1; }
|
||||
| simple_type { $$ = $1; }
|
||||
;
|
||||
|
||||
assignment_pattern<patternp>: // ==IEEE: assignment_pattern
|
||||
|
||||
Reference in New Issue
Block a user