2021-07-14 14:01:03 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Emit C++ for tree
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2025-01-01 14:30:25 +01:00
|
|
|
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
2021-07-14 14:01:03 +02:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
|
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
|
|
|
|
|
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
#include "V3EmitCBase.h"
|
|
|
|
|
#include "V3Error.h"
|
|
|
|
|
|
|
|
|
|
#include <cinttypes>
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Emitter that can emit constant initializer expressions
|
|
|
|
|
|
2023-03-18 17:17:25 +01:00
|
|
|
class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitorConst {
|
2021-07-14 14:01:03 +02:00
|
|
|
// MEMBERS
|
|
|
|
|
uint32_t m_unpackedWord = 0;
|
|
|
|
|
|
|
|
|
|
// METHODS
|
2025-08-19 23:02:10 +02:00
|
|
|
uint32_t tabModulus(const AstNodeDType* dtypep) {
|
2021-12-11 17:22:04 +01:00
|
|
|
const uint32_t elemBytes = dtypep->widthTotalBytes();
|
|
|
|
|
return dtypep->isString() ? 1 // String
|
|
|
|
|
: elemBytes <= 2 ? 8 // CData, SData
|
|
|
|
|
: elemBytes <= 4 ? 4 // IData
|
|
|
|
|
: elemBytes <= 8 ? 2 // QData
|
|
|
|
|
: 1;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-14 14:01:03 +02:00
|
|
|
protected:
|
|
|
|
|
// VISITORS
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstInitArray* nodep) override {
|
2021-07-14 14:01:03 +02:00
|
|
|
VL_RESTORER(m_unpackedWord);
|
2024-08-06 14:48:12 +02:00
|
|
|
if (VN_IS(nodep->dtypep()->skipRefp(), AssocArrayDType)) {
|
2021-12-11 17:29:01 +01:00
|
|
|
// Note the double {{ initializer. The first { starts the initializer of the
|
2024-11-28 19:33:59 +01:00
|
|
|
// VlAssocArray, and the second starts the initializer of m_storage within the
|
|
|
|
|
// VlAssocArray.
|
2021-12-11 17:29:01 +01:00
|
|
|
puts("{");
|
|
|
|
|
ofp()->putsNoTracking("{");
|
|
|
|
|
puts("\n");
|
|
|
|
|
int comma = 0;
|
|
|
|
|
const auto& mapr = nodep->map();
|
|
|
|
|
for (const auto& itr : mapr) {
|
|
|
|
|
if (comma++) putbs(",\n");
|
2024-01-25 03:51:47 +01:00
|
|
|
putns(nodep, cvtToStr(itr.first));
|
2021-12-11 17:29:01 +01:00
|
|
|
ofp()->printf("%" PRIx64 "ULL", itr.first);
|
|
|
|
|
ofp()->putsNoTracking(":");
|
|
|
|
|
ofp()->putsNoTracking("{");
|
2023-03-18 17:17:25 +01:00
|
|
|
iterateConst(nodep->getIndexValuep(itr.first));
|
2021-12-11 17:29:01 +01:00
|
|
|
ofp()->putsNoTracking("}");
|
|
|
|
|
}
|
|
|
|
|
puts("\n");
|
|
|
|
|
puts("}");
|
|
|
|
|
ofp()->putsNoTracking("}");
|
|
|
|
|
} else if (const AstUnpackArrayDType* const dtypep
|
|
|
|
|
= VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
|
2022-03-27 21:27:40 +02:00
|
|
|
const uint64_t size = dtypep->elementsConst();
|
2021-12-11 17:29:01 +01:00
|
|
|
const uint32_t tabMod = tabModulus(dtypep->subDTypep());
|
|
|
|
|
// Note the double {{ initializer. The first { starts the initializer of the
|
|
|
|
|
// VlUnpacked, and the second starts the initializer of m_storage within the
|
|
|
|
|
// VlUnpacked.
|
|
|
|
|
puts("{");
|
|
|
|
|
ofp()->putsNoTracking("{");
|
|
|
|
|
puts("\n");
|
2022-03-27 21:27:40 +02:00
|
|
|
for (uint64_t n = 0; n < size; ++n) {
|
2021-12-11 17:29:01 +01:00
|
|
|
m_unpackedWord = n;
|
|
|
|
|
if (n) puts((n % tabMod) ? ", " : ",\n");
|
2024-10-10 13:20:44 +02:00
|
|
|
AstNode* const itemp = nodep->getIndexDefaultedValuep(n);
|
|
|
|
|
UASSERT_OBJ(itemp, nodep, "Missing array init element");
|
|
|
|
|
iterateConst(itemp);
|
2021-12-11 17:29:01 +01:00
|
|
|
}
|
|
|
|
|
puts("\n");
|
|
|
|
|
puts("}");
|
|
|
|
|
ofp()->putsNoTracking("}");
|
|
|
|
|
} else {
|
|
|
|
|
nodep->v3fatalSrc("Array initializer has non-array dtype");
|
2021-07-14 14:01:03 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstInitItem* nodep) override { // LCOV_EXCL_START
|
2025-03-24 00:51:54 +01:00
|
|
|
nodep->v3fatalSrc("Handled by AstInitArray");
|
2021-07-14 14:01:03 +02:00
|
|
|
} // LCOV_EXCL_STOP
|
|
|
|
|
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstConst* nodep) override {
|
2021-07-14 14:01:03 +02:00
|
|
|
const V3Number& num = nodep->num();
|
|
|
|
|
UASSERT_OBJ(!num.isFourState(), nodep, "4-state value in constant pool");
|
2025-10-04 13:23:13 +02:00
|
|
|
putns(nodep, num.emitC());
|
2021-07-14 14:01:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Default
|
2022-09-16 12:22:11 +02:00
|
|
|
void visit(AstNode* nodep) override { // LCOV_EXCL_START
|
2021-07-14 14:01:03 +02:00
|
|
|
nodep->v3fatalSrc("Unknown node type reached EmitCConstInit: " << nodep->prettyTypeName());
|
|
|
|
|
} // LCOV_EXCL_STOP
|
|
|
|
|
};
|