CIRCT  19.0.0git
FIRRTL.cpp
Go to the documentation of this file.
1 //===- FIRRTL.cpp - C interface for the FIRRTL dialect --------------------===//
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 
15 #include "mlir/CAPI/IR.h"
16 #include "mlir/CAPI/Registration.h"
17 #include "mlir/CAPI/Support.h"
18 #include "llvm/Support/JSON.h"
19 
20 using namespace circt;
21 using namespace firrtl;
22 
23 namespace json = llvm::json;
24 
25 //===----------------------------------------------------------------------===//
26 // Dialect API.
27 //===----------------------------------------------------------------------===//
28 
30  circt::firrtl::FIRRTLDialect)
31 
32 //===----------------------------------------------------------------------===//
33 // Type API.
34 //===----------------------------------------------------------------------===//
35 
36 MlirType firrtlTypeGetUInt(MlirContext ctx, int32_t width) {
37  return wrap(UIntType::get(unwrap(ctx), width));
38 }
39 
40 MlirType firrtlTypeGetSInt(MlirContext ctx, int32_t width) {
41  return wrap(SIntType::get(unwrap(ctx), width));
42 }
43 
44 MlirType firrtlTypeGetClock(MlirContext ctx) {
45  return wrap(ClockType::get(unwrap(ctx)));
46 }
47 
48 MlirType firrtlTypeGetReset(MlirContext ctx) {
49  return wrap(ResetType::get(unwrap(ctx)));
50 }
51 
52 MlirType firrtlTypeGetAsyncReset(MlirContext ctx) {
53  return wrap(AsyncResetType::get(unwrap(ctx)));
54 }
55 
56 MlirType firrtlTypeGetAnalog(MlirContext ctx, int32_t width) {
57  return wrap(AnalogType::get(unwrap(ctx), width));
58 }
59 
60 MlirType firrtlTypeGetVector(MlirContext ctx, MlirType element, size_t count) {
61  auto baseType = cast<FIRRTLBaseType>(unwrap(element));
62  assert(baseType && "element must be base type");
63 
64  return wrap(FVectorType::get(baseType, count));
65 }
66 
67 bool firrtlTypeIsAOpenBundle(MlirType type) {
68  return isa<OpenBundleType>(unwrap(type));
69 }
70 
71 MlirType firrtlTypeGetBundle(MlirContext ctx, size_t count,
72  const FIRRTLBundleField *fields) {
73  bool bundleCompatible = true;
74  SmallVector<OpenBundleType::BundleElement, 4> bundleFields;
75 
76  bundleFields.reserve(count);
77 
78  for (size_t i = 0; i < count; i++) {
79  auto field = fields[i];
80  auto type = cast<FIRRTLType>(unwrap(field.type));
81  bundleFields.emplace_back(unwrap(field.name), field.isFlip, type);
82  bundleCompatible &= isa<BundleType::ElementType>(type);
83  }
84 
85  // Try to emit base-only bundle.
86  if (bundleCompatible) {
87  auto bundleFieldsMapped = llvm::map_range(bundleFields, [](auto field) {
88  return BundleType::BundleElement{
89  field.name, field.isFlip, cast<BundleType::ElementType>(field.type)};
90  });
91  return wrap(
92  BundleType::get(unwrap(ctx), llvm::to_vector(bundleFieldsMapped)));
93  }
94  return wrap(OpenBundleType::get(unwrap(ctx), bundleFields));
95 }
96 
97 unsigned firrtlTypeGetBundleFieldIndex(MlirType type, MlirStringRef fieldName) {
98  std::optional<unsigned> fieldIndex;
99  if (auto bundleType = dyn_cast<BundleType>(unwrap(type))) {
100  fieldIndex = bundleType.getElementIndex(unwrap(fieldName));
101  } else if (auto bundleType = dyn_cast<OpenBundleType>(unwrap(type))) {
102  fieldIndex = bundleType.getElementIndex(unwrap(fieldName));
103  } else {
104  llvm_unreachable("must be a bundle type");
105  }
106  assert(fieldIndex.has_value() && "unknown field");
107  return fieldIndex.value();
108 }
109 
110 MlirType firrtlTypeGetRef(MlirType target, bool forceable) {
111  auto baseType = dyn_cast<FIRRTLBaseType>(unwrap(target));
112  assert(baseType && "target must be base type");
113 
114  return wrap(RefType::get(baseType, forceable));
115 }
116 
117 MlirType firrtlTypeGetAnyRef(MlirContext ctx) {
118  return wrap(AnyRefType::get(unwrap(ctx)));
119 }
120 
121 MlirType firrtlTypeGetInteger(MlirContext ctx) {
122  return wrap(FIntegerType::get(unwrap(ctx)));
123 }
124 
125 MlirType firrtlTypeGetDouble(MlirContext ctx) {
126  return wrap(DoubleType::get(unwrap(ctx)));
127 }
128 
129 MlirType firrtlTypeGetString(MlirContext ctx) {
130  return wrap(StringType::get(unwrap(ctx)));
131 }
132 
133 MlirType firrtlTypeGetBoolean(MlirContext ctx) {
134  return wrap(BoolType::get(unwrap(ctx)));
135 }
136 
137 MlirType firrtlTypeGetPath(MlirContext ctx) {
138  return wrap(PathType::get(unwrap(ctx)));
139 }
140 
141 MlirType firrtlTypeGetList(MlirContext ctx, MlirType elementType) {
142  auto type = dyn_cast<PropertyType>(unwrap(elementType));
143  assert(type && "element must be property type");
144 
145  return wrap(ListType::get(unwrap(ctx), type));
146 }
147 
148 MlirType firrtlTypeGetClass(MlirContext ctx, MlirAttribute name,
149  size_t numberOfElements,
150  const FIRRTLClassElement *elements) {
151  auto nameSymbol = dyn_cast<FlatSymbolRefAttr>(unwrap(name));
152  assert(nameSymbol && "name must be FlatSymbolRefAttr");
153 
154  SmallVector<ClassElement, 4> classElements;
155  classElements.reserve(numberOfElements);
156 
157  for (size_t i = 0; i < numberOfElements; i++) {
158  auto element = elements[i];
159  auto dir = element.direction == FIRRTL_DIRECTION_IN ? Direction::In
160  : Direction::Out;
161  classElements.emplace_back(unwrap(element.name), unwrap(element.type), dir);
162  }
163  return wrap(ClassType::get(unwrap(ctx), nameSymbol, classElements));
164 }
165 
166 MlirType firrtlTypeGetMaskType(MlirType type) {
167  auto baseType = type_dyn_cast<FIRRTLBaseType>(unwrap(type));
168  assert(baseType && "unexpected type, must be base type");
169  return wrap(baseType.getMaskType());
170 }
171 
172 //===----------------------------------------------------------------------===//
173 // Attribute API.
174 //===----------------------------------------------------------------------===//
175 
176 MlirAttribute firrtlAttrGetConvention(MlirContext ctx,
177  FIRRTLConvention convention) {
178  Convention value;
179 
180  switch (convention) {
182  value = Convention::Internal;
183  break;
185  value = Convention::Scalarized;
186  break;
187  }
188 
189  return wrap(ConventionAttr::get(unwrap(ctx), value));
190 }
191 
192 MlirAttribute firrtlAttrGetPortDirs(MlirContext ctx, size_t count,
193  const FIRRTLDirection *dirs) {
194  static_assert(FIRRTL_DIRECTION_IN ==
195  static_cast<std::underlying_type_t<Direction>>(Direction::In));
196  static_assert(FIRRTL_DIRECTION_OUT ==
197  static_cast<std::underlying_type_t<Direction>>(Direction::Out));
198 
199  // FIXME: The `reinterpret_cast` here may voilate strict aliasing rule. Is
200  // there a better way?
202  unwrap(ctx), ArrayRef(reinterpret_cast<const Direction *>(dirs), count)));
203 }
204 
205 MlirAttribute firrtlAttrGetParamDecl(MlirContext ctx, MlirIdentifier name,
206  MlirType type, MlirAttribute value) {
207  return wrap(ParamDeclAttr::get(unwrap(ctx), unwrap(name), unwrap(type),
208  unwrap(value)));
209 }
210 
211 MlirAttribute firrtlAttrGetNameKind(MlirContext ctx, FIRRTLNameKind nameKind) {
212  NameKindEnum value;
213 
214  switch (nameKind) {
216  value = NameKindEnum::DroppableName;
217  break;
219  value = NameKindEnum::InterestingName;
220  break;
221  }
222 
223  return wrap(NameKindEnumAttr::get(unwrap(ctx), value));
224 }
225 
226 MlirAttribute firrtlAttrGetRUW(MlirContext ctx, FIRRTLRUW ruw) {
227  RUWAttr value;
228 
229  switch (ruw) {
231  value = RUWAttr::Undefined;
232  break;
233  case FIRRTL_RUW_OLD:
234  value = RUWAttr::Old;
235  break;
236  case FIRRTL_RUW_NEW:
237  value = RUWAttr::New;
238  break;
239  }
240 
241  return wrap(RUWAttrAttr::get(unwrap(ctx), value));
242 }
243 
244 MlirAttribute firrtlAttrGetMemInit(MlirContext ctx, MlirIdentifier filename,
245  bool isBinary, bool isInline) {
246  return wrap(
247  MemoryInitAttr::get(unwrap(ctx), unwrap(filename), isBinary, isInline));
248 }
249 
250 MlirAttribute firrtlAttrGetMemDir(MlirContext ctx, FIRRTLMemDir dir) {
251  MemDirAttr value;
252 
253  switch (dir) {
255  value = MemDirAttr::Infer;
256  break;
257  case FIRRTL_MEM_DIR_READ:
258  value = MemDirAttr::Read;
259  break;
261  value = MemDirAttr::Write;
262  break;
264  value = MemDirAttr::ReadWrite;
265  break;
266  }
267 
268  return wrap(MemDirAttrAttr::get(unwrap(ctx), value));
269 }
270 
271 MlirAttribute firrtlAttrGetEventControl(MlirContext ctx,
272  FIRRTLEventControl eventControl) {
273  EventControl value;
274 
275  switch (eventControl) {
277  value = EventControl::AtPosEdge;
278  break;
280  value = EventControl::AtNegEdge;
281  break;
283  value = EventControl::AtEdge;
284  break;
285  }
286 
287  return wrap(EventControlAttr::get(unwrap(ctx), value));
288 }
289 
290 MlirAttribute firrtlAttrGetIntegerFromString(MlirType type, unsigned numBits,
291  MlirStringRef str, uint8_t radix) {
292  auto value = APInt{numBits, unwrap(str), radix};
293  return wrap(IntegerAttr::get(unwrap(type), value));
294 }
295 
297  Flow flowValue;
298 
299  switch (flow) {
301  flowValue = Flow::None;
302  break;
304  flowValue = Flow::Source;
305  break;
307  flowValue = Flow::Sink;
308  break;
310  flowValue = Flow::Duplex;
311  break;
312  }
313 
314  auto flowResult = firrtl::foldFlow(unwrap(value), flowValue);
315 
316  switch (flowResult) {
317  case Flow::None:
318  return FIRRTL_VALUE_FLOW_NONE;
319  case Flow::Source:
321  case Flow::Sink:
322  return FIRRTL_VALUE_FLOW_SINK;
323  case Flow::Duplex:
325  }
326  llvm_unreachable("invalid flow");
327 }
328 
330  MlirContext ctx, MlirStringRef annotationsStr,
331  MlirAttribute *importedAnnotationsArray) {
332  auto annotations = json::parse(unwrap(annotationsStr));
333  if (!annotations) {
334  return false;
335  }
336 
337  auto *ctxUnwrapped = unwrap(ctx);
338 
339  json::Path::Root root;
340  SmallVector<Attribute> annos;
341  if (!importAnnotationsFromJSONRaw(annotations.get(), annos, root,
342  ctxUnwrapped)) {
343  return false;
344  }
345 
346  *importedAnnotationsArray = wrap(ArrayAttr::get(ctxUnwrapped, annos));
347  return true;
348 }
assert(baseType &&"element must be base type")
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
MlirType elementType
Definition: CHIRRTL.cpp:29
MlirAttribute firrtlAttrGetMemDir(MlirContext ctx, FIRRTLMemDir dir)
Definition: FIRRTL.cpp:250
MlirType firrtlTypeGetAsyncReset(MlirContext ctx)
Definition: FIRRTL.cpp:52
MlirType firrtlTypeGetList(MlirContext ctx, MlirType elementType)
Definition: FIRRTL.cpp:141
MlirAttribute firrtlAttrGetIntegerFromString(MlirType type, unsigned numBits, MlirStringRef str, uint8_t radix)
Definition: FIRRTL.cpp:290
MlirType firrtlTypeGetBoolean(MlirContext ctx)
Definition: FIRRTL.cpp:133
MlirType firrtlTypeGetDouble(MlirContext ctx)
Definition: FIRRTL.cpp:125
MlirType firrtlTypeGetPath(MlirContext ctx)
Definition: FIRRTL.cpp:137
MlirType firrtlTypeGetString(MlirContext ctx)
Definition: FIRRTL.cpp:129
MlirType firrtlTypeGetAnalog(MlirContext ctx, int32_t width)
Definition: FIRRTL.cpp:56
MlirType firrtlTypeGetInteger(MlirContext ctx)
Definition: FIRRTL.cpp:121
MlirAttribute firrtlAttrGetConvention(MlirContext ctx, FIRRTLConvention convention)
Definition: FIRRTL.cpp:176
int32_t width
Definition: FIRRTL.cpp:36
MlirType firrtlTypeGetClock(MlirContext ctx)
Definition: FIRRTL.cpp:44
MlirType firrtlTypeGetReset(MlirContext ctx)
Definition: FIRRTL.cpp:48
MlirType firrtlTypeGetVector(MlirContext ctx, MlirType element, size_t count)
Definition: FIRRTL.cpp:60
bool firrtlImportAnnotationsFromJSONRaw(MlirContext ctx, MlirStringRef annotationsStr, MlirAttribute *importedAnnotationsArray)
Definition: FIRRTL.cpp:329
MlirType firrtlTypeGetAnyRef(MlirContext ctx)
Definition: FIRRTL.cpp:117
MlirAttribute firrtlAttrGetPortDirs(MlirContext ctx, size_t count, const FIRRTLDirection *dirs)
Definition: FIRRTL.cpp:192
MlirType firrtlTypeGetClass(MlirContext ctx, MlirAttribute name, size_t numberOfElements, const FIRRTLClassElement *elements)
Definition: FIRRTL.cpp:148
bool firrtlTypeIsAOpenBundle(MlirType type)
Definition: FIRRTL.cpp:67
MlirType firrtlTypeGetMaskType(MlirType type)
Definition: FIRRTL.cpp:166
MlirType firrtlTypeGetSInt(MlirContext ctx, int32_t width)
Definition: FIRRTL.cpp:40
MlirType firrtlTypeGetRef(MlirType target, bool forceable)
Definition: FIRRTL.cpp:110
MlirType firrtlTypeGetBundle(MlirContext ctx, size_t count, const FIRRTLBundleField *fields)
Definition: FIRRTL.cpp:71
MlirAttribute firrtlAttrGetEventControl(MlirContext ctx, FIRRTLEventControl eventControl)
Definition: FIRRTL.cpp:271
MlirAttribute firrtlAttrGetParamDecl(MlirContext ctx, MlirIdentifier name, MlirType type, MlirAttribute value)
Definition: FIRRTL.cpp:205
MlirAttribute firrtlAttrGetMemInit(MlirContext ctx, MlirIdentifier filename, bool isBinary, bool isInline)
Definition: FIRRTL.cpp:244
FIRRTLValueFlow firrtlValueFoldFlow(MlirValue value, FIRRTLValueFlow flow)
Definition: FIRRTL.cpp:296
MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(FIRRTL, firrtl, circt::firrtl::FIRRTLDialect) MlirType firrtlTypeGetUInt(MlirContext ctx
MlirAttribute firrtlAttrGetRUW(MlirContext ctx, FIRRTLRUW ruw)
Definition: FIRRTL.cpp:226
MlirAttribute firrtlAttrGetNameKind(MlirContext ctx, FIRRTLNameKind nameKind)
Definition: FIRRTL.cpp:211
unsigned firrtlTypeGetBundleFieldIndex(MlirType type, MlirStringRef fieldName)
Definition: FIRRTL.cpp:97
FIRRTLValueFlow
Definition: FIRRTL.h:59
@ FIRRTL_VALUE_FLOW_SOURCE
Definition: FIRRTL.h:61
@ FIRRTL_VALUE_FLOW_NONE
Definition: FIRRTL.h:60
@ FIRRTL_VALUE_FLOW_SINK
Definition: FIRRTL.h:62
@ FIRRTL_VALUE_FLOW_DUPLEX
Definition: FIRRTL.h:63
FIRRTLNameKind
Definition: FIRRTL.h:31
@ FIRRTL_NAME_KIND_DROPPABLE_NAME
Definition: FIRRTL.h:32
@ FIRRTL_NAME_KIND_INTERESTING_NAME
Definition: FIRRTL.h:33
FIRRTLMemDir
Definition: FIRRTL.h:44
@ FIRRTL_MEM_DIR_INFER
Definition: FIRRTL.h:45
@ FIRRTL_MEM_DIR_READ
Definition: FIRRTL.h:46
@ FIRRTL_MEM_DIR_READ_WRITE
Definition: FIRRTL.h:48
@ FIRRTL_MEM_DIR_WRITE
Definition: FIRRTL.h:47
MLIR_CAPI_EXPORTED MlirType firrtlTypeGetUInt(MlirContext ctx, int32_t width)
FIRRTLEventControl
Definition: FIRRTL.h:52
@ FIRRTL_EVENT_CONTROL_AT_POS_EDGE
Definition: FIRRTL.h:53
@ FIRRTL_EVENT_CONTROL_AT_NEG_EDGE
Definition: FIRRTL.h:54
@ FIRRTL_EVENT_CONTROL_AT_EDGE
Definition: FIRRTL.h:55
FIRRTLDirection
Definition: FIRRTL.h:25
@ FIRRTL_DIRECTION_OUT
Definition: FIRRTL.h:27
@ FIRRTL_DIRECTION_IN
Definition: FIRRTL.h:26
FIRRTLRUW
Definition: FIRRTL.h:37
@ FIRRTL_RUW_OLD
Definition: FIRRTL.h:39
@ FIRRTL_RUW_UNDEFINED
Definition: FIRRTL.h:38
@ FIRRTL_RUW_NEW
Definition: FIRRTL.h:40
FIRRTLConvention
Definition: FIRRTL.h:19
@ FIRRTL_CONVENTION_SCALARIZED
Definition: FIRRTL.h:21
@ FIRRTL_CONVENTION_INTERNAL
Definition: FIRRTL.h:20
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
Definition: OM.cpp:96
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Definition: CalyxOps.cpp:54
mlir::DenseBoolArrayAttr packAttribute(MLIRContext *context, ArrayRef< Direction > directions)
Return a DenseBoolArrayAttr containing the packed representation of an array of directions.
Direction
This represents the direction of a single port.
Flow foldFlow(Value val, Flow accumulatedFlow=Flow::Source)
Compute the flow for a Value, val, as determined by the FIRRTL specification.
Definition: FIRRTLOps.cpp:182
bool importAnnotationsFromJSONRaw(llvm::json::Value &value, SmallVectorImpl< Attribute > &annotations, llvm::json::Path path, MLIRContext *context)
Deserialize a JSON value into FIRRTL Annotations.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
FIRRTLDirection direction
Definition: FIRRTL.h:77