diff --git a/docs/command-line-ref.dox b/docs/command-line-ref.dox index 44441bc58..22a03a511 100644 --- a/docs/command-line-ref.dox +++ b/docs/command-line-ref.dox @@ -245,6 +245,11 @@ symbols are dumped. When dumping AST to JSON, include source line and file information. +`--ast-json-detailed-types` + +When dumping AST to JSON, include expanded type information in the output instead of +condensing all types into a human-friendly string. + @section compilation-limits Compilation `--top ` diff --git a/include/slang/ast/ASTSerializer.h b/include/slang/ast/ASTSerializer.h index 6d0d476a6..15df981a3 100644 --- a/include/slang/ast/ASTSerializer.h +++ b/include/slang/ast/ASTSerializer.h @@ -7,6 +7,7 @@ //------------------------------------------------------------------------------ #pragma once +#include "slang/util/Hash.h" #include "slang/util/Util.h" namespace slang { @@ -42,6 +43,10 @@ class SLANG_EXPORT ASTSerializer { /// information should be included in the JSON output. void setIncludeSourceInfo(bool set) { includeSourceInfo = set; } + /// Sets a flag that indicates whether detailed type information + /// is included in the output. + void setDetailedTypeInfo(bool set) { detailedTypeInfo = set; } + /// Serializes a symbol to JSON. void serialize(const Symbol& symbol, bool inMembersArray = false); @@ -174,6 +179,8 @@ class SLANG_EXPORT ASTSerializer { JsonWriter& writer; bool includeAddrs = true; bool includeSourceInfo = false; + bool detailedTypeInfo = false; + flat_hash_set visiting; }; } // namespace slang::ast diff --git a/include/slang/ast/types/AllTypes.h b/include/slang/ast/types/AllTypes.h index 3cd0fd639..66f1e83ae 100644 --- a/include/slang/ast/types/AllTypes.h +++ b/include/slang/ast/types/AllTypes.h @@ -66,6 +66,8 @@ class SLANG_EXPORT ScalarType : public IntegralType { ScalarType(Kind scalarKind); ScalarType(Kind scalarKind, bool isSigned); + void serializeTo(ASTSerializer&) const {} + static bool isKind(SymbolKind kind) { return kind == SymbolKind::ScalarType; } }; @@ -78,6 +80,8 @@ class SLANG_EXPORT PredefinedIntegerType : public IntegralType { PredefinedIntegerType(Kind integerKind); PredefinedIntegerType(Kind integerKind, bool isSigned); + void serializeTo(ASTSerializer&) const {} + static bool isDefaultSigned(Kind integerKind); static bool isKind(SymbolKind kind) { return kind == SymbolKind::PredefinedIntegerType; } @@ -93,6 +97,7 @@ class SLANG_EXPORT FloatingType : public Type { explicit FloatingType(Kind floatKind); ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::FloatingType; } }; @@ -111,6 +116,8 @@ class SLANG_EXPORT EnumType : public IntegralType, public Scope { EnumType(Compilation& compilation, SourceLocation loc, const Type& baseType, const ASTContext& context); + void serializeTo(ASTSerializer& serializer) const; + static const Type& fromSyntax(Compilation& compilation, const syntax::EnumTypeSyntax& syntax, const ASTContext& context, function_ref insertCB); @@ -161,6 +168,8 @@ class SLANG_EXPORT PackedArrayType : public IntegralType { PackedArrayType(const Type& elementType, ConstantRange range, bitwidth_t fullWidth); + void serializeTo(ASTSerializer& serializer) const; + static const Type& fromSyntax(const Scope& scope, const Type& elementType, const EvaluatedDimension& dimension, const syntax::SyntaxNode& syntax); @@ -190,6 +199,8 @@ class SLANG_EXPORT FixedSizeUnpackedArrayType : public Type { FixedSizeUnpackedArrayType(const Type& elementType, ConstantRange range, uint64_t selectableWidth, uint64_t bitstreamWidth); + void serializeTo(ASTSerializer& serializer) const; + static const Type& fromDims(const Scope& scope, const Type& elementType, std::span dimensions, syntax::DeferredSourceRange sourceRange); @@ -211,6 +222,7 @@ class SLANG_EXPORT DynamicArrayType : public Type { explicit DynamicArrayType(const Type& elementType); ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer& serializer) const; static bool isKind(SymbolKind kind) { return kind == SymbolKind::DynamicArrayType; } }; @@ -228,6 +240,7 @@ class SLANG_EXPORT DPIOpenArrayType : public Type { DPIOpenArrayType(const Type& elementType, bool isPacked); ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer& serializer) const; static bool isKind(SymbolKind kind) { return kind == SymbolKind::DPIOpenArrayType; } }; @@ -247,6 +260,7 @@ class SLANG_EXPORT AssociativeArrayType : public Type { /// @returns true if the array has a wildcard index type bool hasWildcardIndexType() const { return indexType == nullptr; } ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer& serializer) const; static bool isKind(SymbolKind kind) { return kind == SymbolKind::AssociativeArrayType; } }; @@ -263,6 +277,7 @@ class SLANG_EXPORT QueueType : public Type { QueueType(const Type& elementType, uint32_t maxBound); ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer& serializer) const; static bool isKind(SymbolKind kind) { return kind == SymbolKind::QueueType; } }; @@ -276,6 +291,8 @@ class SLANG_EXPORT PackedStructType : public IntegralType, public Scope { PackedStructType(Compilation& compilation, bool isSigned, SourceLocation loc, const ASTContext& context); + void serializeTo(ASTSerializer&) const {} + static const Type& fromSyntax(Compilation& compilation, const syntax::StructUnionTypeSyntax& syntax, const ASTContext& context); @@ -300,6 +317,8 @@ class SLANG_EXPORT UnpackedStructType : public Type, public Scope { UnpackedStructType(Compilation& compilation, SourceLocation loc, const ASTContext& context); + void serializeTo(ASTSerializer&) const {} + static const Type& fromSyntax(const ASTContext& context, const syntax::StructUnionTypeSyntax& syntax); @@ -327,6 +346,8 @@ class SLANG_EXPORT PackedUnionType : public IntegralType, public Scope { PackedUnionType(Compilation& compilation, bool isSigned, bool isTagged, bool isSoft, SourceLocation loc, const ASTContext& context); + void serializeTo(ASTSerializer& serializer) const; + static const Type& fromSyntax(Compilation& compilation, const syntax::StructUnionTypeSyntax& syntax, const ASTContext& context); @@ -355,6 +376,8 @@ class SLANG_EXPORT UnpackedUnionType : public Type, public Scope { UnpackedUnionType(Compilation& compilation, bool isTagged, SourceLocation loc, const ASTContext& context); + void serializeTo(ASTSerializer& serializer) const; + static const Type& fromSyntax(const ASTContext& context, const syntax::StructUnionTypeSyntax& syntax); @@ -372,6 +395,7 @@ class SLANG_EXPORT VoidType : public Type { VoidType() : Type(SymbolKind::VoidType, "void", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::VoidType; } }; @@ -385,6 +409,7 @@ class SLANG_EXPORT NullType : public Type { NullType() : Type(SymbolKind::NullType, "null", SourceLocation()) {} ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::NullType; } }; @@ -395,6 +420,7 @@ class SLANG_EXPORT CHandleType : public Type { CHandleType() : Type(SymbolKind::CHandleType, "chandle", SourceLocation()) {} ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::CHandleType; } }; @@ -405,6 +431,7 @@ class SLANG_EXPORT StringType : public Type { StringType() : Type(SymbolKind::StringType, "string", SourceLocation()) {} ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::StringType; } }; @@ -416,6 +443,7 @@ class SLANG_EXPORT EventType : public Type { EventType() : Type(SymbolKind::EventType, "event", SourceLocation()) {} ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::EventType; } }; @@ -427,6 +455,7 @@ class SLANG_EXPORT UnboundedType : public Type { UnboundedType() : Type(SymbolKind::UnboundedType, "$", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::UnboundedType; } }; @@ -437,6 +466,7 @@ class SLANG_EXPORT TypeRefType : public Type { TypeRefType() : Type(SymbolKind::TypeRefType, "type reference", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::TypeRefType; } }; @@ -447,6 +477,7 @@ class SLANG_EXPORT UntypedType : public Type { UntypedType() : Type(SymbolKind::UntypedType, "untyped", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::UntypedType; } }; @@ -457,6 +488,7 @@ class SLANG_EXPORT SequenceType : public Type { SequenceType() : Type(SymbolKind::SequenceType, "sequence", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::SequenceType; } }; @@ -467,6 +499,7 @@ class SLANG_EXPORT PropertyType : public Type { PropertyType() : Type(SymbolKind::PropertyType, "property", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::PropertyType; } }; @@ -490,6 +523,7 @@ class SLANG_EXPORT VirtualInterfaceType : public Type { isRealIface(isRealIface) {} ConstantValue getDefaultValueImpl() const; + void serializeTo(ASTSerializer& serializer) const; static const Type& fromSyntax(const ASTContext& context, const syntax::VirtualInterfaceTypeSyntax& syntax); @@ -576,6 +610,7 @@ class SLANG_EXPORT ErrorType : public Type { ErrorType() : Type(SymbolKind::ErrorType, "", SourceLocation()) {} ConstantValue getDefaultValueImpl() const { return nullptr; } + void serializeTo(ASTSerializer&) const {} static bool isKind(SymbolKind kind) { return kind == SymbolKind::ErrorType; } diff --git a/source/ast/ASTSerializer.cpp b/source/ast/ASTSerializer.cpp index 6f2425664..9eeb459a3 100644 --- a/source/ast/ASTSerializer.cpp +++ b/source/ast/ASTSerializer.cpp @@ -243,13 +243,20 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) { } writer.endObject(); } - else if constexpr (std::is_base_of_v && !std::is_same_v && - !std::is_same_v && !std::is_same_v) { - writer.writeValue(elem.toString()); - } else { if constexpr (std::is_base_of_v) { - if (!inMembersArray) { + // If we're not including detailed type info, we can just write the type name, + // unless this a type alias, class, or covergroup. Otherwise we will fall through + // and serialize full detailed type info. + if (!detailedTypeInfo && (!inMembersArray || (!std::is_same_v && + !std::is_same_v && + !std::is_same_v))) { + writer.writeValue(elem.toString()); + return; + } + + // Avoid infinite loops with recursive types. + if (!visiting.insert(&elem).second) { writer.writeValue(elem.toString()); return; } @@ -261,6 +268,10 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) { return; } + // Ignore transparent members. + if (elem.kind == SymbolKind::TransparentMember) + return; + writer.startObject(); write("name", elem.name); write("kind", toString(elem.kind)); @@ -284,7 +295,8 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) { } if constexpr (std::is_base_of_v) { - write("type", elem.getType()); + if (elem.kind != SymbolKind::EnumValue) + write("type", elem.getType()); if (auto init = elem.getInitializer()) write("initializer", *init); @@ -304,6 +316,10 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) { } writer.endObject(); + + if constexpr (std::is_base_of_v) { + visiting.erase(&elem); + } } } diff --git a/source/ast/types/AllTypes.cpp b/source/ast/types/AllTypes.cpp index 8a2ca43c0..9562b1e9e 100644 --- a/source/ast/types/AllTypes.cpp +++ b/source/ast/types/AllTypes.cpp @@ -7,6 +7,8 @@ //------------------------------------------------------------------------------ #include "slang/ast/types/AllTypes.h" +#include + #include "slang/ast/ASTContext.h" #include "slang/ast/ASTSerializer.h" #include "slang/ast/Compilation.h" @@ -558,6 +560,10 @@ const Type& EnumType::findDefinition(Compilation& comp, const EnumTypeSyntax& sy return comp.getErrorType(); } +void EnumType::serializeTo(ASTSerializer& serializer) const { + serializer.write("baseType", baseType); +} + EnumValueSymbol::EnumValueSymbol(std::string_view name, SourceLocation loc) : ValueSymbol(SymbolKind::EnumValue, name, loc, DeclaredTypeFlags::InitializerCantSeeParent) { } @@ -679,6 +685,11 @@ const Type& PackedArrayType::fromDim(const Scope& scope, const Type& elementType return *result; } +void PackedArrayType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); + serializer.write("range", fmt::format("[{}:{}]", range.left, range.right)); +} + FixedSizeUnpackedArrayType::FixedSizeUnpackedArrayType(const Type& elementType, ConstantRange range, uint64_t selectableWidth, uint64_t bitstreamWidth) : @@ -725,6 +736,11 @@ ConstantValue FixedSizeUnpackedArrayType::getDefaultValueImpl() const { return std::vector(range.width(), elementType.getDefaultValue()); } +void FixedSizeUnpackedArrayType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); + serializer.write("range", fmt::format("[{}:{}]", range.left, range.right)); +} + DynamicArrayType::DynamicArrayType(const Type& elementType) : Type(SymbolKind::DynamicArrayType, "", SourceLocation()), elementType(elementType) { } @@ -733,6 +749,10 @@ ConstantValue DynamicArrayType::getDefaultValueImpl() const { return std::vector(); } +void DynamicArrayType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); +} + DPIOpenArrayType::DPIOpenArrayType(const Type& elementType, bool isPacked) : Type(SymbolKind::DPIOpenArrayType, "", SourceLocation()), elementType(elementType), isPacked(isPacked) { @@ -742,6 +762,11 @@ ConstantValue DPIOpenArrayType::getDefaultValueImpl() const { return nullptr; } +void DPIOpenArrayType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); + serializer.write("isPacked", isPacked); +} + AssociativeArrayType::AssociativeArrayType(const Type& elementType, const Type* indexType) : Type(SymbolKind::AssociativeArrayType, "", SourceLocation()), elementType(elementType), indexType(indexType) { @@ -751,6 +776,12 @@ ConstantValue AssociativeArrayType::getDefaultValueImpl() const { return AssociativeArray(); } +void AssociativeArrayType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); + if (indexType) + serializer.write("indexType", *indexType); +} + QueueType::QueueType(const Type& elementType, uint32_t maxBound) : Type(SymbolKind::QueueType, "", SourceLocation()), elementType(elementType), maxBound(maxBound) { @@ -762,6 +793,11 @@ ConstantValue QueueType::getDefaultValueImpl() const { return result; } +void QueueType::serializeTo(ASTSerializer& serializer) const { + serializer.write("elementType", elementType); + serializer.write("maxBound", maxBound); +} + PackedStructType::PackedStructType(Compilation& compilation, bool isSigned, SourceLocation loc, const ASTContext& context) : IntegralType(SymbolKind::PackedStructType, "", loc, 0, isSigned, false), @@ -1026,6 +1062,11 @@ const Type& PackedUnionType::fromSyntax(Compilation& comp, const StructUnionType return createPackedDims(context, unionType, syntax.dimensions); } +void PackedUnionType::serializeTo(ASTSerializer& serializer) const { + serializer.write("isTagged", isTagged); + serializer.write("isSoft", isSoft); +} + UnpackedUnionType::UnpackedUnionType(Compilation& compilation, bool isTagged, SourceLocation loc, const ASTContext& context) : Type(SymbolKind::UnpackedUnionType, "", loc), Scope(compilation, this), @@ -1104,6 +1145,10 @@ const Type& UnpackedUnionType::fromSyntax(const ASTContext& context, return *result; } +void UnpackedUnionType::serializeTo(ASTSerializer& serializer) const { + serializer.write("isTagged", isTagged); +} + ConstantValue NullType::getDefaultValueImpl() const { return ConstantValue::NullPlaceholder{}; } @@ -1168,6 +1213,10 @@ ConstantValue VirtualInterfaceType::getDefaultValueImpl() const { return ConstantValue::NullPlaceholder{}; } +void VirtualInterfaceType::serializeTo(ASTSerializer& serializer) const { + serializer.write("target", toString()); +} + ForwardingTypedefSymbol& ForwardingTypedefSymbol::fromSyntax( const Scope& scope, const ForwardTypedefDeclarationSyntax& syntax) { diff --git a/tests/regression/CMakeLists.txt b/tests/regression/CMakeLists.txt index 7280d00e5..37a055f40 100644 --- a/tests/regression/CMakeLists.txt +++ b/tests/regression/CMakeLists.txt @@ -9,4 +9,4 @@ add_test(NAME regression_wire_module COMMAND slang::driver "${CMAKE_CURRENT_LIST_DIR}/wire_module.v") add_test(NAME regression_all_file COMMAND slang::driver "${CMAKE_CURRENT_LIST_DIR}/all.sv" - "--ast-json=-") + "--ast-json=-" "--ast-json-detailed-types") diff --git a/tests/unittests/ast/SerializerTests.cpp b/tests/unittests/ast/SerializerTests.cpp index 69516f1db..e553fca0a 100644 --- a/tests/unittests/ast/SerializerTests.cpp +++ b/tests/unittests/ast/SerializerTests.cpp @@ -7,13 +7,14 @@ #include "slang/ast/ASTVisitor.h" #include "slang/text/Json.h" -std::string serialize(Compilation& comp, bool sourceInfo = false) { +std::string serialize(Compilation& comp, bool sourceInfo = false, bool detailedTypeInfo = false) { JsonWriter writer; writer.setPrettyPrint(true); ASTSerializer serializer(comp, writer); serializer.setIncludeAddresses(false); serializer.setIncludeSourceInfo(sourceInfo); + serializer.setDetailedTypeInfo(detailedTypeInfo); serializer.serialize(comp.getRoot()); return "\n"s + std::string(writer.view()); @@ -135,20 +136,6 @@ endmodule "source_line": 2, "source_column": 8, "members": [ - { - "name": "STATE_0", - "kind": "TransparentMember", - "source_file": "source", - "source_line": 4, - "source_column": 9 - }, - { - "name": "STATE_1", - "kind": "TransparentMember", - "source_file": "source", - "source_line": 5, - "source_column": 9 - }, { "name": "STATE", "kind": "TypeAlias", @@ -918,7 +905,7 @@ typedef enum logic [1:0] { compilation.addSyntaxTree(tree); NO_COMPILATION_ERRORS; - auto result = serialize(compilation); + auto result = serialize(compilation, false, true); CHECK(result == R"( { "name": "$root", @@ -931,33 +918,233 @@ typedef enum logic [1:0] { { "name": "INST", "kind": "TypeAlias", - "target": "union packed{logic[31:0] inst;}u$1" + "target": { + "name": "", + "kind": "PackedUnionType", + "members": [ + { + "name": "inst", + "kind": "Field", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[31:0]" + }, + "lifetime": "Automatic", + "bitOffset": 0, + "fieldIndex": 0 + } + ], + "isTagged": false, + "isSoft": false + } }, { "name": "CONTAINER", "kind": "TypeAlias", - "target": "struct packed{INST inst;logic another_signal;}s$1" - }, - { - "name": "BYTE", - "kind": "TransparentMember" - }, - { - "name": "HALF", - "kind": "TransparentMember" - }, - { - "name": "WORD", - "kind": "TransparentMember" - }, - { - "name": "DOUBLE", - "kind": "TransparentMember" + "target": { + "name": "", + "kind": "PackedStructType", + "members": [ + { + "name": "inst", + "kind": "Field", + "type": { + "name": "INST", + "kind": "TypeAlias", + "target": { + "name": "", + "kind": "PackedUnionType", + "members": [ + { + "name": "inst", + "kind": "Field", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[31:0]" + }, + "lifetime": "Automatic", + "bitOffset": 0, + "fieldIndex": 0 + } + ], + "isTagged": false, + "isSoft": false + } + }, + "lifetime": "Automatic", + "bitOffset": 1, + "fieldIndex": 0 + }, + { + "name": "another_signal", + "kind": "Field", + "type": { + "name": "logic", + "kind": "ScalarType" + }, + "lifetime": "Automatic", + "bitOffset": 0, + "fieldIndex": 1 + } + ] + } }, { "name": "MEM_SIZE", "kind": "TypeAlias", - "target": "enum{BYTE=2'd0,HALF=2'd1,WORD=2'd2,DOUBLE=2'd3}MEM_SIZE" + "target": { + "name": "MEM_SIZE", + "kind": "EnumType", + "members": [ + { + "name": "BYTE", + "kind": "EnumValue", + "initializer": { + "kind": "Conversion", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "operand": { + "kind": "IntegerLiteral", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "bit", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "value": "2'b0", + "constant": "2'b0" + }, + "constant": "2'b0" + }, + "value": "2'b0" + }, + { + "name": "HALF", + "kind": "EnumValue", + "initializer": { + "kind": "Conversion", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "operand": { + "kind": "IntegerLiteral", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "bit", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "value": "2'b1", + "constant": "2'b1" + }, + "constant": "2'b1" + }, + "value": "2'b1" + }, + { + "name": "WORD", + "kind": "EnumValue", + "initializer": { + "kind": "Conversion", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "operand": { + "kind": "IntegerLiteral", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "bit", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "value": "2'b10", + "constant": "2'b10" + }, + "constant": "2'b10" + }, + "value": "2'b10" + }, + { + "name": "DOUBLE", + "kind": "EnumValue", + "initializer": { + "kind": "Conversion", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "operand": { + "kind": "IntegerLiteral", + "type": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "bit", + "kind": "ScalarType" + }, + "range": "[1:0]" + }, + "value": "2'b11", + "constant": "2'b11" + }, + "constant": "2'b11" + }, + "value": "2'b11" + } + ], + "baseType": { + "name": "", + "kind": "PackedArrayType", + "elementType": { + "name": "logic", + "kind": "ScalarType" + }, + "range": "[1:0]" + } + } } ] } diff --git a/tools/driver/slang_main.cpp b/tools/driver/slang_main.cpp index 4b296eb5f..e34fca6b7 100644 --- a/tools/driver/slang_main.cpp +++ b/tools/driver/slang_main.cpp @@ -25,12 +25,14 @@ using namespace slang::ast; using namespace slang::driver; void printJson(Compilation& compilation, const std::string& fileName, - const std::vector& scopes, bool includeSourceInfo) { + const std::vector& scopes, bool includeSourceInfo, bool detailedTypes) { JsonWriter writer; writer.setPrettyPrint(true); ASTSerializer serializer(compilation, writer); serializer.setIncludeSourceInfo(includeSourceInfo); + serializer.setDetailedTypeInfo(detailedTypes); + if (scopes.empty()) { serializer.startObject(); serializer.writeProperty("design"); @@ -106,6 +108,10 @@ int driverMain(int argc, TArgs argv) { driver.cmdLine.add("--ast-json-source-info", includeSourceInfo, "When dumping AST to JSON, include source line and file information"); + std::optional serializeDetailedTypes; + driver.cmdLine.add("--ast-json-detailed-types", serializeDetailedTypes, + "When dumping AST to JSON, expand out all type information"); + std::optional timeTrace; driver.cmdLine.add("--time-trace", timeTrace, "Do performance profiling of the slang compiler and output " @@ -166,9 +172,11 @@ int driverMain(int argc, TArgs argv) { TimeTraceScope timeScope("elaboration"sv, ""sv); auto compilation = driver.createCompilation(); ok &= driver.reportCompilation(*compilation, quiet == true); - if (astJsonFile) + + if (astJsonFile) { printJson(*compilation, *astJsonFile, astJsonScopes, - includeSourceInfo == true); + includeSourceInfo == true, serializeDetailedTypes == true); + } } } }