CIRCT  19.0.0git
ESIModule.cpp
Go to the documentation of this file.
1 //===- ESIModule.cpp - ESI API pybind module ------------------------------===//
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 #include "DialectModules.h"
10 
12 
13 #include "circt-c/Dialect/ESI.h"
14 #include "mlir-c/Bindings/Python/Interop.h"
15 
16 #include "mlir/Bindings/Python/PybindAdaptors.h"
17 #include "mlir/CAPI/IR.h"
18 #include "mlir/CAPI/Support.h"
19 
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallVector.h"
22 
23 #include "PybindUtils.h"
24 #include <pybind11/pybind11.h>
25 #include <pybind11/stl.h>
26 namespace py = pybind11;
27 
28 using namespace circt::esi;
29 
30 //===----------------------------------------------------------------------===//
31 // The main entry point into the ESI Assembly API.
32 //===----------------------------------------------------------------------===//
33 
34 // Mapping from unique identifier to python callback. We use std::string
35 // pointers since we also need to allocate memory for the string.
36 llvm::DenseMap<std::string *, PyObject *> serviceGenFuncLookup;
37 static MlirLogicalResult serviceGenFunc(MlirOperation reqOp,
38  MlirOperation declOp, void *userData) {
39  std::string *name = static_cast<std::string *>(userData);
40  py::handle genFunc(serviceGenFuncLookup[name]);
41  py::gil_scoped_acquire();
42  py::object rc = genFunc(reqOp);
43  return rc.cast<bool>() ? mlirLogicalResultSuccess()
44  : mlirLogicalResultFailure();
45 }
46 
47 void registerServiceGenerator(std::string name, py::object genFunc) {
48  std::string *n = new std::string(name);
49  genFunc.inc_ref();
50  serviceGenFuncLookup[n] = genFunc.ptr();
52 }
53 
54 class PyAppIDIndex {
55 public:
56  PyAppIDIndex(MlirOperation root) { index = circtESIAppIDIndexGet(root); }
57  PyAppIDIndex(const PyAppIDIndex &) = delete;
59 
60  MlirAttribute getChildAppIDsOf(MlirOperation op) const {
61  return circtESIAppIDIndexGetChildAppIDsOf(index, op);
62  }
63 
64  py::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid,
65  MlirLocation loc) const {
66  MlirAttribute path =
67  circtESIAppIDIndexGetAppIDPath(index, fromMod, appid, loc);
68  if (path.ptr == nullptr)
69  return py::none();
70  return py::cast(path);
71  }
72 
73 private:
75 };
76 
77 using namespace mlir::python::adaptors;
78 
80  m.doc() = "ESI Python Native Extension";
82 
83  m.def("registerServiceGenerator", registerServiceGenerator,
84  "Register a service generator for a given service name.",
85  py::arg("impl_type"), py::arg("generator"));
86 
87  mlir_type_subclass(m, "ChannelType", circtESITypeIsAChannelType)
88  .def_classmethod(
89  "get",
90  [](py::object cls, MlirType inner, uint32_t signaling = 0) {
91  if (circtESITypeIsAChannelType(inner))
92  return cls(inner);
93  return cls(circtESIChannelTypeGet(inner, signaling));
94  },
95  py::arg("cls"), py::arg("inner"), py::arg("signaling") = 0)
96  .def_property_readonly(
97  "inner", [](MlirType self) { return circtESIChannelGetInner(self); })
98  .def_property_readonly("signaling", [](MlirType self) {
99  return circtESIChannelGetSignaling(self);
100  });
101 
102  mlir_type_subclass(m, "AnyType", circtESITypeIsAnAnyType)
103  .def_classmethod(
104  "get",
105  [](py::object cls, MlirContext ctxt) {
106  return cls(circtESIAnyTypeGet(ctxt));
107  },
108  py::arg("self"), py::arg("ctxt") = nullptr);
109 
110  mlir_type_subclass(m, "ListType", circtESITypeIsAListType)
111  .def_classmethod(
112  "get",
113  [](py::object cls, MlirType inner) {
114  return cls(circtESIListTypeGet(inner));
115  },
116  py::arg("cls"), py::arg("inner"))
117  .def_property_readonly("element_type", [](MlirType self) {
118  return circtESIListTypeGetElementType(self);
119  });
120 
121  py::enum_<ChannelDirection>(m, "ChannelDirection")
122  .value("TO", ChannelDirection::to)
123  .value("FROM", ChannelDirection::from);
124  mlir_type_subclass(m, "BundleType", circtESITypeIsABundleType)
125  .def_classmethod(
126  "get",
127  [](py::object cls, std::vector<py::tuple> channelTuples,
128  bool resettable, MlirContext ctxt) {
129  llvm::SmallVector<CirctESIBundleTypeBundleChannel, 4> channels(
130  llvm::map_range(channelTuples, [ctxt](py::tuple t) {
131  std::string name = py::cast<std::string>(t[0]);
133  mlirIdentifierGet(ctxt, mlirStringRefCreate(
134  name.data(), name.length())),
135  (uint32_t)py::cast<ChannelDirection>(t[1]),
136  py::cast<MlirType>(t[2])};
137  }));
138  return cls(circtESIBundleTypeGet(ctxt, channels.size(),
139  channels.data(), resettable));
140  },
141  py::arg("cls"), py::arg("channels"), py::arg("resettable"),
142  py::arg("ctxt") = nullptr)
143  .def_property_readonly("resettable", &circtESIBundleTypeGetResettable)
144  .def_property_readonly("channels", [](MlirType bundleType) {
145  std::vector<py::tuple> channels;
146  size_t numChannels = circtESIBundleTypeGetNumChannels(bundleType);
147  for (size_t i = 0; i < numChannels; ++i) {
149  circtESIBundleTypeGetChannel(bundleType, i);
150  MlirStringRef name = mlirIdentifierStr(channel.name);
151  channels.push_back(py::make_tuple(py::str(name.data, name.length),
152  (ChannelDirection)channel.direction,
153  channel.channelType));
154  }
155  return channels;
156  });
157 
158  mlir_attribute_subclass(m, "AppIDAttr", circtESIAttributeIsAnAppIDAttr)
159  .def_classmethod(
160  "get",
161  [](py::object cls, std::string name, std::optional<uint64_t> index,
162  MlirContext ctxt) {
163  if (index.has_value())
164  return cls(circtESIAppIDAttrGet(ctxt, wrap(name), index.value()));
165  return cls(circtESIAppIDAttrGetNoIdx(ctxt, wrap(name)));
166  },
167  "Create an AppID attribute", py::arg("cls"), py::arg("name"),
168  py::arg("index") = py::none(), py::arg("context") = py::none())
169  .def_property_readonly("name",
170  [](MlirAttribute self) {
171  llvm::StringRef name =
173  return std::string(name.data(), name.size());
174  })
175  .def_property_readonly("index", [](MlirAttribute self) -> py::object {
176  uint64_t index;
177  if (circtESIAppIDAttrGetIndex(self, &index))
178  return py::cast(index);
179  return py::none();
180  });
181 
182  mlir_attribute_subclass(m, "AppIDPathAttr",
184  .def_classmethod(
185  "get",
186  [](py::object cls, MlirAttribute root,
187  std::vector<MlirAttribute> path, MlirContext ctxt) {
188  return cls(
189  circtESIAppIDAttrPathGet(ctxt, root, path.size(), path.data()));
190  },
191  "Create an AppIDPath attribute", py::arg("cls"), py::arg("root"),
192  py::arg("path"), py::arg("context") = py::none())
193  .def_property_readonly("root", &circtESIAppIDAttrPathGetRoot)
194  .def("__len__", &circtESIAppIDAttrPathGetNumComponents)
195  .def("__getitem__", &circtESIAppIDAttrPathGetComponent);
196 
197  py::class_<PyAppIDIndex>(m, "AppIDIndex")
198  .def(py::init<MlirOperation>(), py::arg("root"))
199  .def("get_child_appids_of", &PyAppIDIndex::getChildAppIDsOf,
200  "Return a dictionary of AppIDAttrs to ArrayAttr of InnerRefAttrs "
201  "containing the relative paths to the leaf of the particular "
202  "AppIDAttr. Argument MUST be HWModuleLike.",
203  py::arg("mod"))
204  .def("get_appid_path", &PyAppIDIndex::getAppIDPathAttr,
205  "Return an array of InnerNameRefAttrs representing the relative "
206  "path to 'appid' from 'fromMod'.",
207  py::arg("from_mod"), py::arg("appid"),
208  py::arg("query_site") = py::none());
209 }
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
void registerServiceGenerator(std::string name, py::object genFunc)
Definition: ESIModule.cpp:47
static MlirLogicalResult serviceGenFunc(MlirOperation reqOp, MlirOperation declOp, void *userData)
Definition: ESIModule.cpp:37
llvm::DenseMap< std::string *, PyObject * > serviceGenFuncLookup
Definition: ESIModule.cpp:36
MLIR_CAPI_EXPORTED uint32_t circtESIChannelGetSignaling(MlirType channelType)
Definition: ESI.cpp:44
MLIR_CAPI_EXPORTED MlirType circtESIBundleTypeGet(MlirContext, size_t numChannels, const CirctESIBundleTypeBundleChannel *channels, bool resettable)
Definition: ESI.cpp:102
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrGet(MlirContext, MlirStringRef name, uint64_t index)
Definition: ESI.cpp:138
MLIR_CAPI_EXPORTED bool circtESIBundleTypeGetResettable(MlirType bundle)
Definition: ESI.cpp:116
MLIR_CAPI_EXPORTED bool circtESITypeIsAnAnyType(MlirType type)
Definition: ESI.cpp:48
MLIR_CAPI_EXPORTED void circtESIRegisterGlobalServiceGenerator(MlirStringRef impl_type, CirctESIServiceGeneratorFunc, void *userData)
Definition: ESI.cpp:85
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDIndexGetChildAppIDsOf(CirctESIAppIDIndex, MlirOperation)
Definition: ESI.cpp:199
MLIR_CAPI_EXPORTED MlirType circtESIChannelTypeGet(MlirType inner, uint32_t signaling)
Definition: ESI.cpp:33
MLIR_CAPI_EXPORTED MlirType circtESIChannelGetInner(MlirType channelType)
Definition: ESI.cpp:41
MLIR_CAPI_EXPORTED CirctESIBundleTypeBundleChannel circtESIBundleTypeGetChannel(MlirType bundle, size_t idx)
Definition: ESI.cpp:122
MLIR_CAPI_EXPORTED void circtESIAppIDIndexFree(CirctESIAppIDIndex)
Free an AppIDIndex.
Definition: ESI.cpp:194
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrGetNoIdx(MlirContext ctxt, MlirStringRef name)
Definition: ESI.cpp:143
MLIR_CAPI_EXPORTED uint64_t circtESIAppIDAttrPathGetNumComponents(MlirAttribute attr)
Definition: ESI.cpp:174
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDIndexGetAppIDPath(CirctESIAppIDIndex, MlirOperation fromMod, MlirAttribute appid, MlirLocation loc)
Definition: ESI.cpp:205
MLIR_CAPI_EXPORTED MlirStringRef circtESIAppIDAttrGetName(MlirAttribute attr)
Definition: ESI.cpp:147
MLIR_CAPI_EXPORTED bool circtESITypeIsAChannelType(MlirType type)
Definition: ESI.cpp:29
MLIR_CAPI_EXPORTED size_t circtESIBundleTypeGetNumChannels(MlirType bundle)
Definition: ESI.cpp:119
MLIR_CAPI_EXPORTED MlirType circtESIListTypeGetElementType(MlirType channelType)
Definition: ESI.cpp:64
MLIR_CAPI_EXPORTED MlirType circtESIAnyTypeGet(MlirContext)
Definition: ESI.cpp:51
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrPathGetComponent(MlirAttribute attr, uint64_t index)
Definition: ESI.cpp:177
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrPathGet(MlirContext, MlirAttribute root, intptr_t numElements, MlirAttribute const *elements)
Definition: ESI.cpp:162
MLIR_CAPI_EXPORTED MlirType circtESIListTypeGet(MlirType inner)
Definition: ESI.cpp:59
MLIR_CAPI_EXPORTED bool circtESITypeIsABundleType(MlirType type)
Definition: ESI.cpp:99
MLIR_CAPI_EXPORTED bool circtESIAppIDAttrGetIndex(MlirAttribute attr, uint64_t *index)
Definition: ESI.cpp:150
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrPathGetRoot(MlirAttribute attr)
Definition: ESI.cpp:171
MLIR_CAPI_EXPORTED bool circtESIAttributeIsAnAppIDPathAttr(MlirAttribute)
Definition: ESI.cpp:158
MLIR_CAPI_EXPORTED CirctESIAppIDIndex circtESIAppIDIndexGet(MlirOperation root)
Create an index of appids through which to do appid lookups efficiently.
Definition: ESI.cpp:186
MLIR_CAPI_EXPORTED bool circtESIAttributeIsAnAppIDAttr(MlirAttribute)
Definition: ESI.cpp:134
MLIR_CAPI_EXPORTED bool circtESITypeIsAListType(MlirType type)
Definition: ESI.cpp:55
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
Definition: OM.cpp:96
PyAppIDIndex(const PyAppIDIndex &)=delete
CirctESIAppIDIndex index
Definition: ESIModule.cpp:74
py::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid, MlirLocation loc) const
Definition: ESIModule.cpp:64
PyAppIDIndex(MlirOperation root)
Definition: ESIModule.cpp:56
MlirAttribute getChildAppIDsOf(MlirOperation op) const
Definition: ESIModule.cpp:60
void registerESIPasses()
Definition: ESIPasses.cpp:264
void populateDialectESISubmodule(pybind11::module &m)
MlirIdentifier name
Definition: ESI.h:46