CIRCT  20.0.0git
ImportVerilogInternals.h
Go to the documentation of this file.
1 //===- ImportVerilogInternals.h - Internal implementation details ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // NOLINTNEXTLINE(llvm-header-guard)
10 #ifndef CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H
11 #define CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H
12 
15 #include "circt/Dialect/HW/HWOps.h"
17 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
18 #include "mlir/Dialect/Func/IR/FuncOps.h"
19 #include "slang/ast/ASTVisitor.h"
20 #include "llvm/ADT/ScopedHashTable.h"
21 #include "llvm/Support/Debug.h"
22 #include <map>
23 #include <queue>
24 
25 #define DEBUG_TYPE "import-verilog"
26 
27 namespace circt {
28 namespace ImportVerilog {
29 
30 using moore::Domain;
31 
32 /// Port lowering information.
33 struct PortLowering {
34  const slang::ast::PortSymbol &ast;
35  Location loc;
36  BlockArgument arg;
37 };
38 
39 /// Module lowering information.
41  moore::SVModuleOp op;
42  SmallVector<PortLowering> ports;
43  DenseMap<const slang::syntax::SyntaxNode *, const slang::ast::PortSymbol *>
45 };
46 
47 /// Function lowering information.
49  mlir::func::FuncOp op;
50 };
51 
52 /// Information about a loops continuation and exit blocks relevant while
53 /// lowering the loop's body statements.
54 struct LoopFrame {
55  /// The block to jump to from a `continue` statement.
56  Block *continueBlock;
57  /// The block to jump to from a `break` statement.
58  Block *breakBlock;
59 };
60 
61 /// Hierarchical path information.
62 /// The "hierName" means a different hierarchical name at different module
63 /// levels.
64 /// The "idx" means where the current hierarchical name is on the portlists.
65 /// The "direction" means hierarchical names whether downward(In) or
66 /// upward(Out).
67 struct HierPathInfo {
68  mlir::StringAttr hierName;
69  std::optional<unsigned int> idx;
70  slang::ast::ArgumentDirection direction;
71  const slang::ast::ValueSymbol *valueSym;
72 };
73 
74 /// A helper class to facilitate the conversion from a Slang AST to MLIR
75 /// operations. Keeps track of the destination MLIR module, builders, and
76 /// various worklists and utilities needed for conversion.
77 struct Context {
79  slang::ast::Compilation &compilation, mlir::ModuleOp intoModuleOp,
80  const slang::SourceManager &sourceManager,
84  builder(OpBuilder::atBlockEnd(intoModuleOp.getBody())),
86  Context(const Context &) = delete;
87 
88  /// Return the MLIR context.
89  MLIRContext *getContext() { return intoModuleOp.getContext(); }
90 
91  /// Convert a slang `SourceLocation` into an MLIR `Location`.
92  Location convertLocation(slang::SourceLocation loc);
93  /// Convert a slang `SourceRange` into an MLIR `Location`.
94  Location convertLocation(slang::SourceRange range);
95 
96  /// Convert a slang type into an MLIR type. Returns null on failure. Uses the
97  /// provided location for error reporting, or tries to guess one from the
98  /// given type. Types tend to have unreliable location information, so it's
99  /// generally a good idea to pass in a location.
100  Type convertType(const slang::ast::Type &type, LocationAttr loc = {});
101  Type convertType(const slang::ast::DeclaredType &type);
102 
103  /// Convert hierarchy and structure AST nodes to MLIR ops.
104  LogicalResult convertCompilation();
105  ModuleLowering *
106  convertModuleHeader(const slang::ast::InstanceBodySymbol *module);
107  LogicalResult convertModuleBody(const slang::ast::InstanceBodySymbol *module);
108  LogicalResult convertPackage(const slang::ast::PackageSymbol &package);
109  FunctionLowering *
110  declareFunction(const slang::ast::SubroutineSymbol &subroutine);
111  LogicalResult convertFunction(const slang::ast::SubroutineSymbol &subroutine);
112 
113  // Convert a statement AST node to MLIR ops.
114  LogicalResult convertStatement(const slang::ast::Statement &stmt);
115 
116  // Convert an expression AST node to MLIR ops.
117  Value convertRvalueExpression(const slang::ast::Expression &expr,
118  Type requiredType = {});
119  Value convertLvalueExpression(const slang::ast::Expression &expr);
120 
121  // Traverse the whole AST to collect hierarchical names.
122  LogicalResult
123  collectHierarchicalValues(const slang::ast::Expression &expr,
124  const slang::ast::Symbol &outermostModule);
125  LogicalResult traverseInstanceBody(const slang::ast::Symbol &symbol);
126 
127  // Convert a slang timing control into an MLIR timing control.
128  LogicalResult convertTimingControl(const slang::ast::TimingControl &ctrl,
129  const slang::ast::Statement &stmt);
130 
131  /// Helper function to convert a value to its "truthy" boolean value.
132  Value convertToBool(Value value);
133 
134  /// Helper function to convert a value to its "truthy" boolean value and
135  /// convert it to the given domain.
136  Value convertToBool(Value value, Domain domain);
137 
138  /// Helper function to convert a value to its simple bit vector
139  /// representation, if it has one. Otherwise returns null. Also returns null
140  /// if the given value is null.
141  Value convertToSimpleBitVector(Value value);
142 
143  /// Helper function to insert the necessary operations to cast a value from
144  /// one type to another.
145  Value materializeConversion(Type type, Value value, bool isSigned,
146  Location loc);
147 
148  /// Helper function to materialize an `SVInt` as an SSA value.
149  Value materializeSVInt(const slang::SVInt &svint,
150  const slang::ast::Type &type, Location loc);
151 
152  /// Helper function to materialize a `ConstantValue` as an SSA value. Returns
153  /// null if the constant cannot be materialized.
154  Value materializeConstant(const slang::ConstantValue &constant,
155  const slang::ast::Type &type, Location loc);
156 
157  /// Convert a list of string literal arguments with formatting specifiers and
158  /// arguments to be interpolated into a `!moore.format_string` value. Returns
159  /// failure if an error occurs. Returns a null value if the formatted string
160  /// is trivially empty. Otherwise returns the formatted string.
161  FailureOr<Value> convertFormatString(
162  slang::span<const slang::ast::Expression *const> arguments, Location loc,
163  moore::IntFormat defaultFormat = moore::IntFormat::Decimal,
164  bool appendNewline = false);
165 
166  /// Evaluate the constant value of an expression.
167  slang::ConstantValue evaluateConstant(const slang::ast::Expression &expr);
168 
170  slang::ast::Compilation &compilation;
171  mlir::ModuleOp intoModuleOp;
172  const slang::SourceManager &sourceManager;
174 
175  /// The builder used to create IR operations.
176  OpBuilder builder;
177  /// A symbol table of the MLIR module we are emitting into.
178  SymbolTable symbolTable;
179 
180  /// The top-level operations ordered by their Slang source location. This is
181  /// used to produce IR that follows the source file order.
182  std::map<slang::SourceLocation, Operation *> orderedRootOps;
183 
184  /// How we have lowered modules to MLIR.
185  DenseMap<const slang::ast::InstanceBodySymbol *,
186  std::unique_ptr<ModuleLowering>>
188  /// A list of modules for which the header has been created, but the body has
189  /// not been converted yet.
190  std::queue<const slang::ast::InstanceBodySymbol *> moduleWorklist;
191 
192  /// Functions that have already been converted.
193  DenseMap<const slang::ast::SubroutineSymbol *,
194  std::unique_ptr<FunctionLowering>>
196 
197  /// A table of defined values, such as variables, that may be referred to by
198  /// name in expressions. The expressions use this table to lookup the MLIR
199  /// value that was created for a given declaration in the Slang AST node.
200  using ValueSymbols =
201  llvm::ScopedHashTable<const slang::ast::ValueSymbol *, Value>;
202  using ValueSymbolScope = ValueSymbols::ScopeTy;
204 
205  /// Collect all hierarchical names used for the per module/instance.
206  DenseMap<const slang::ast::InstanceBodySymbol *, SmallVector<HierPathInfo>>
208 
209  /// It's used to collect the repeat hierarchical names on the same path.
210  /// Such as `Top.sub.a` and `sub.a`, they are equivalent. The variable "a"
211  /// will be added to the port list. But we only record once. If we don't do
212  /// that. We will view the strange IR, such as `module @Sub(out y, out y)`;
213  DenseSet<StringAttr> sameHierPaths;
214 
215  /// A stack of assignment left-hand side values. Each assignment will push its
216  /// lowered left-hand side onto this stack before lowering its right-hand
217  /// side. This allows expressions to resolve the opaque
218  /// `LValueReferenceExpression`s in the AST.
219  SmallVector<Value> lvalueStack;
220 
221  /// A stack of loop continuation and exit blocks. Each loop will push the
222  /// relevant info onto this stack, lower its loop body statements, and pop the
223  /// info off the stack again. Continue and break statements encountered as
224  /// part of the loop body statements will use this information to branch to
225  /// the correct block.
226  SmallVector<LoopFrame> loopStack;
227 
228  /// A listener called for every variable or net being read. This can be used
229  /// to collect all variables read as part of an expression or statement, for
230  /// example to populate the list of observed signals in an implicit event
231  /// control `@*`.
232  std::function<void(moore::ReadOp)> rvalueReadCallback;
233 };
234 
235 } // namespace ImportVerilog
236 } // namespace circt
237 
238 #endif // CONVERSION_IMPORTVERILOG_IMPORTVERILOGINTERNALS_H
Domain
The number of values each bit of a type can assume.
Definition: MooreTypes.h:47
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
Options that control how Verilog input files are parsed and processed.
Definition: ImportVerilog.h:37
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
LogicalResult convertFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function.
Definition: Structure.cpp:943
Value materializeConversion(Type type, Value value, bool isSigned, Location loc)
Helper function to insert the necessary operations to cast a value from one type to another.
ModuleLowering * convertModuleHeader(const slang::ast::InstanceBodySymbol *module)
Convert a module and its ports to an empty module op in the IR.
Definition: Structure.cpp:614
Value convertLvalueExpression(const slang::ast::Expression &expr)
Value materializeConstant(const slang::ConstantValue &constant, const slang::ast::Type &type, Location loc)
Helper function to materialize a ConstantValue as an SSA value.
SmallVector< LoopFrame > loopStack
A stack of loop continuation and exit blocks.
LogicalResult convertModuleBody(const slang::ast::InstanceBodySymbol *module)
Convert a module's body to the corresponding IR ops.
Definition: Structure.cpp:786
slang::ConstantValue evaluateConstant(const slang::ast::Expression &expr)
Evaluate the constant value of an expression.
slang::ast::Compilation & compilation
LogicalResult convertTimingControl(const slang::ast::TimingControl &ctrl, const slang::ast::Statement &stmt)
OpBuilder builder
The builder used to create IR operations.
std::queue< const slang::ast::InstanceBodySymbol * > moduleWorklist
A list of modules for which the header has been created, but the body has not been converted yet.
std::function< void(moore::ReadOp)> rvalueReadCallback
A listener called for every variable or net being read.
Context(const Context &)=delete
std::map< slang::SourceLocation, Operation * > orderedRootOps
The top-level operations ordered by their Slang source location.
Type convertType(const slang::ast::Type &type, LocationAttr loc={})
Convert a slang type into an MLIR type.
Definition: Types.cpp:167
DenseMap< const slang::ast::SubroutineSymbol *, std::unique_ptr< FunctionLowering > > functions
Functions that have already been converted.
Value materializeSVInt(const slang::SVInt &svint, const slang::ast::Type &type, Location loc)
Helper function to materialize an SVInt as an SSA value.
SmallDenseMap< slang::BufferID, StringRef > & bufferFilePaths
Value convertToBool(Value value)
Helper function to convert a value to its "truthy" boolean value.
FailureOr< Value > convertFormatString(slang::span< const slang::ast::Expression *const > arguments, Location loc, moore::IntFormat defaultFormat=moore::IntFormat::Decimal, bool appendNewline=false)
Convert a list of string literal arguments with formatting specifiers and arguments to be interpolate...
ValueSymbols::ScopeTy ValueSymbolScope
const ImportVerilogOptions & options
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
llvm::ScopedHashTable< const slang::ast::ValueSymbol *, Value > ValueSymbols
A table of defined values, such as variables, that may be referred to by name in expressions.
Value convertToSimpleBitVector(Value value)
Helper function to convert a value to its simple bit vector representation, if it has one.
LogicalResult traverseInstanceBody(const slang::ast::Symbol &symbol)
const slang::SourceManager & sourceManager
DenseSet< StringAttr > sameHierPaths
It's used to collect the repeat hierarchical names on the same path.
SymbolTable symbolTable
A symbol table of the MLIR module we are emitting into.
DenseMap< const slang::ast::InstanceBodySymbol *, SmallVector< HierPathInfo > > hierPaths
Collect all hierarchical names used for the per module/instance.
FunctionLowering * declareFunction(const slang::ast::SubroutineSymbol &subroutine)
Convert a function and its arguments to a function declaration in the IR.
Definition: Structure.cpp:870
Context(const ImportVerilogOptions &options, slang::ast::Compilation &compilation, mlir::ModuleOp intoModuleOp, const slang::SourceManager &sourceManager, SmallDenseMap< slang::BufferID, StringRef > &bufferFilePaths)
LogicalResult collectHierarchicalValues(const slang::ast::Expression &expr, const slang::ast::Symbol &outermostModule)
LogicalResult convertPackage(const slang::ast::PackageSymbol &package)
Convert a package and its contents.
Definition: Structure.cpp:855
LogicalResult convertCompilation()
Convert hierarchy and structure AST nodes to MLIR ops.
Definition: Structure.cpp:572
MLIRContext * getContext()
Return the MLIR context.
LogicalResult convertStatement(const slang::ast::Statement &stmt)
Definition: Statements.cpp:695
SmallVector< Value > lvalueStack
A stack of assignment left-hand side values.
DenseMap< const slang::ast::InstanceBodySymbol *, std::unique_ptr< ModuleLowering > > modules
How we have lowered modules to MLIR.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.
Hierarchical path information.
slang::ast::ArgumentDirection direction
const slang::ast::ValueSymbol * valueSym
std::optional< unsigned int > idx
Information about a loops continuation and exit blocks relevant while lowering the loop's body statem...
Block * breakBlock
The block to jump to from a break statement.
Block * continueBlock
The block to jump to from a continue statement.
DenseMap< const slang::syntax::SyntaxNode *, const slang::ast::PortSymbol * > portsBySyntaxNode
const slang::ast::PortSymbol & ast