CIRCT 24.0.0git
Loading...
Searching...
No Matches
LoweringOptions.cpp
Go to the documentation of this file.
1//===- LoweringOptions.cpp - CIRCT Lowering Options -----------------------===//
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// Options for controlling the lowering process. Contains command line
10// option definitions and support.
11//
12//===----------------------------------------------------------------------===//
13
16#include "mlir/IR/BuiltinOps.h"
17
18using namespace circt;
19using namespace mlir;
20
21//===----------------------------------------------------------------------===//
22// LoweringOptions
23//===----------------------------------------------------------------------===//
24
25LoweringOptions::LoweringOptions(StringRef options, ErrorHandlerT errorHandler)
26 : LoweringOptions() {
27 parse(options, errorHandler);
28}
29
31 parseFromAttribute(module);
32}
33
34static std::optional<LoweringOptions::LocationInfoStyle>
35parseLocationInfoStyle(StringRef option) {
36 return llvm::StringSwitch<std::optional<LoweringOptions::LocationInfoStyle>>(
37 option)
38 .Case("plain", LoweringOptions::Plain)
39 .Case("wrapInAtSquareBracket", LoweringOptions::WrapInAtSquareBracket)
40 .Case("none", LoweringOptions::None)
41 .Default(std::nullopt);
42}
43
44static std::optional<LoweringOptions::WireSpillingHeuristic>
45parseWireSpillingHeuristic(StringRef option) {
46 return llvm::StringSwitch<
47 std::optional<LoweringOptions::WireSpillingHeuristic>>(option)
48 .Case("spillLargeTermsWithNamehints",
50 .Default(std::nullopt);
51}
52
53static std::optional<LoweringOptions::VarOpDeclStyle>
54parseVarOpDeclStyle(StringRef option) {
55 return llvm::StringSwitch<std::optional<LoweringOptions::VarOpDeclStyle>>(
56 option)
60 .Default(std::nullopt);
61}
62
63static std::optional<LoweringOptions::EmitPortType>
64parseEmitPortType(StringRef option) {
65 return llvm::StringSwitch<std::optional<LoweringOptions::EmitPortType>>(
66 option)
70 .Default(std::nullopt);
71}
72
73void LoweringOptions::parse(StringRef text, ErrorHandlerT errorHandler) {
74 while (!text.empty()) {
75 // Remove the first option from the text.
76 auto split = text.split(",");
77 auto option = split.first.trim();
78 text = split.second;
79 if (option == "") {
80 // Empty options are fine.
81 } else if (option == "noAlwaysComb") {
82 noAlwaysComb = true;
83 } else if (option == "exprInEventControl") {
85 } else if (option == "disallowPackedArrays") {
87 } else if (option == "disallowPackedStructAssignments") {
89 } else if (option == "disallowLocalVariables") {
91 } else if (option == "verifLabels") {
92 enforceVerifLabels = true;
93 } else if (option.consume_front("emittedLineLength=")) {
94 if (option.getAsInteger(10, emittedLineLength)) {
95 errorHandler("expected integer source width");
98 errorHandler("line length '" + Twine(emittedLineLength) +
99 "' exceeds maximum of " + Twine(MAX_LINE_LENGTH));
101 }
102 } else if (option == "explicitBitcast") {
103 explicitBitcast = true;
104 } else if (option == "emitReplicatedOpsToHeader") {
106 } else if (option.consume_front("maximumNumberOfTermsPerExpression=")) {
107 if (option.getAsInteger(10, maximumNumberOfTermsPerExpression)) {
108 errorHandler("expected integer source width");
110 }
111 } else if (option.consume_front("locationInfoStyle=")) {
112 if (auto style = parseLocationInfoStyle(option)) {
113 locationInfoStyle = *style;
114 } else {
115 errorHandler("expected 'plain', 'wrapInAtSquareBracket', or 'none'");
116 }
117 } else if (option == "disallowPortDeclSharing") {
119 } else if (option == "printDebugInfo") {
120 printDebugInfo = true;
121 } else if (option == "disallowExpressionInliningInPorts") {
123 } else if (option == "disallowMuxInlining") {
124 disallowMuxInlining = true;
125 } else if (option == "disallowReplicate") {
126 disallowReplicate = true;
127 } else if (option == "mitigateVivadoArrayIndexConstPropBug") {
129 } else if (option.consume_front("wireSpillingHeuristic=")) {
130 if (auto heuristic = parseWireSpillingHeuristic(option)) {
131 wireSpillingHeuristicSet |= *heuristic;
132 } else {
133 errorHandler("expected ''spillLargeTermsWithNamehints'");
134 }
135 } else if (option.consume_front("svVarDeclStyle=")) {
136 if (auto style = parseVarOpDeclStyle(option)) {
137 varOpDeclStyle = *style;
138 } else {
139 errorHandler("expected 'varLogic', 'logic', or 'reg'");
140 }
141 } else if (option.consume_front("wireSpillingNamehintTermLimit=")) {
142 if (option.getAsInteger(10, wireSpillingNamehintTermLimit)) {
143 errorHandler(
144 "expected integer for number of namehint heurstic term limit");
146 }
147 } else if (option.consume_front("svPortDeclStyle=")) {
148 if (auto style = parseEmitPortType(option)) {
149 emitPortType = *style;
150 } else {
151 errorHandler("expected 'varLogic', 'wire', or 'none'");
152 }
153 } else if (option == "emitBindComments") {
154 emitBindComments = true;
155 } else if (option == "omitVersionComment") {
156 omitVersionComment = true;
157 } else if (option == "caseInsensitiveKeywords") {
159 } else if (option == "emitVerilogLocations") {
161 } else if (option == "fixUpEmptyModules") {
162 fixUpEmptyModules = true;
163 } else if (option == "disallowClockedAssertions") {
165 } else if (option == "disallowDeclAssignments") {
167 } else if (option == "alwaysEmitBeginEnd") {
168 alwaysEmitBeginEnd = true;
169 } else {
170 errorHandler(llvm::Twine("unknown style option \'") + option + "\'");
171 // We continue parsing options after a failure.
172 }
173 }
174}
175
176std::string LoweringOptions::toString() const {
177 std::string options = "";
178 // All options should add a trailing comma to simplify the code.
179 if (noAlwaysComb)
180 options += "noAlwaysComb,";
182 options += "exprInEventControl,";
184 options += "disallowPackedArrays,";
186 options += "disallowPackedStructAssignments,";
188 options += "disallowLocalVariables,";
190 options += "verifLabels,";
191 if (explicitBitcast)
192 options += "explicitBitcast,";
194 options += "emitReplicatedOpsToHeader,";
196 options += "locationInfoStyle=wrapInAtSquareBracket,";
198 options += "locationInfoStyle=none,";
200 options += "disallowPortDeclSharing,";
201 if (printDebugInfo)
202 options += "printDebugInfo,";
205 options += "wireSpillingHeuristic=spillLargeTermsWithNamehints,";
207 options += "svVarDeclStyle=logic,";
209 options += "svVarDeclStyle=reg,";
211 options += "disallowExpressionInliningInPorts,";
213 options += "disallowMuxInlining,";
215 options += "disallowReplicate,";
217 options += "mitigateVivadoArrayIndexConstPropBug,";
218
220 options += "emittedLineLength=" + std::to_string(emittedLineLength) + ',';
222 options += "maximumNumberOfTermsPerExpression=" +
223 std::to_string(maximumNumberOfTermsPerExpression) + ',';
225 options += "svPortDeclStyle=wire,";
227 options += "svPortDeclStyle=varLogic,";
229 options += "emitBindComments,";
231 options += "omitVersionComment,";
233 options += "caseInsensitiveKeywords,";
235 options += "emitVerilogLocations,";
237 options += "fixUpEmptyModules,";
239 options += "disallowClockedAssertions,";
241 options += "disallowDeclAssignments,";
243 options += "alwaysEmitBeginEnd,";
244
245 // Remove a trailing comma if present.
246 if (!options.empty()) {
247 assert(options.back() == ',' && "all options should add a trailing comma");
248 options.pop_back();
249 }
250 return options;
251}
252
253StringAttr LoweringOptions::getAttributeFrom(ModuleOp module) {
254 return module->getAttrOfType<StringAttr>("circt.loweringOptions");
255}
256
257void LoweringOptions::setAsAttribute(ModuleOp module) {
258 module->setAttr("circt.loweringOptions",
259 StringAttr::get(module.getContext(), toString()));
260}
261
263 if (auto styleAttr = getAttributeFrom(module))
264 parse(styleAttr.getValue(), [&](Twine error) { module.emitError(error); });
265}
266
267static_assert((LoweringOptions::MAX_LINE_LENGTH ==
269 "Exported limits for emitted line length not aligned with "
270 "underlying maximum supported");
assert(baseType &&"element must be base type")
static std::optional< LoweringOptions::LocationInfoStyle > parseLocationInfoStyle(StringRef option)
static std::optional< LoweringOptions::WireSpillingHeuristic > parseWireSpillingHeuristic(StringRef option)
static std::optional< LoweringOptions::EmitPortType > parseEmitPortType(StringRef option)
static std::optional< LoweringOptions::VarOpDeclStyle > parseVarOpDeclStyle(StringRef option)
static constexpr uint32_t kMaxMargin
Largest supported target line length.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Options which control the emission from CIRCT to Verilog.
bool isWireSpillingHeuristicEnabled(WireSpillingHeuristic heurisic) const
bool noAlwaysComb
If true, emits sv.alwayscomb as Verilog always @(*) statements.
bool mitigateVivadoArrayIndexConstPropBug
If true, every expression used as an array index is driven by a wire, and the wire is marked as (* ke...
bool disallowLocalVariables
If true, do not emit SystemVerilog locally scoped "automatic" or logic declarations - emit top level ...
bool omitVersionComment
If true, do not emit a version comment at the top of each verilog file.
bool enforceVerifLabels
If true, verification statements like assert, assume, and cover will always be emitted with a label.
bool disallowExpressionInliningInPorts
If true, every expression passed to an instance port is driven by a wire.
bool printDebugInfo
Print debug info.
llvm::function_ref< void(llvm::Twine)> ErrorHandlerT
Error callback type used to indicate errors parsing the options string.
unsigned maximumNumberOfTermsPerExpression
void setAsAttribute(mlir::ModuleOp module)
Write the verilog emitter options to a module's attributes.
enum circt::LoweringOptions::LocationInfoStyle locationInfoStyle
enum circt::LoweringOptions::EmitPortType emitPortType
bool disallowPortDeclSharing
If true, every port is declared separately (each includes direction and type (e.g....
bool disallowPackedArrays
If true, eliminate packed arrays for tools that don't support them (e.g.
bool explicitBitcast
Add an explicit bitcast for avoiding bitwidth mismatch LINT errors.
bool disallowReplicate
If true, expand comb.replicate into an explicit concatenation instead of emitting the {N{....
bool disallowMuxInlining
If true, every mux expression is spilled to a wire.
bool fixUpEmptyModules
If true, add a dummy wire to empty modules to prevent tools from regarding the module as blackbox.
bool disallowPackedStructAssignments
If true, eliminate packed struct assignments in favor of a wire + assignments to the individual field...
void parse(llvm::StringRef options, ErrorHandlerT callback)
Read in options from a string, overriding only the set options in the string.
static mlir::StringAttr getAttributeFrom(mlir::ModuleOp module)
Return the value of the circt.loweringOptions in the specified module if present, or a null attribute...
bool caseInsensitiveKeywords
If true, then unique names that collide with keywords case insensitively.
void parseFromAttribute(mlir::ModuleOp module)
Load any emitter options from the module.
bool alwaysEmitBeginEnd
If true, always emit begin/end blocks around if/else/always bodies, even when there is only a single ...
bool emitReplicatedOpsToHeader
If true, replicated ops are emitted to a header file.
std::string toString() const
Returns a string representation of the options.
LoweringOptions()=default
Create a LoweringOptions with the default values.
bool allowExprInEventControl
If true, expressions are allowed in the sensitivity list of always statements, otherwise they are for...
bool emitVerilogLocations
If true, then update the the mlir to include output verilog locations.
bool emitBindComments
If true, emit a comment wherever an instance wasn't printed, because it's emitted elsewhere as a bind...
enum circt::LoweringOptions::VarOpDeclStyle varOpDeclStyle