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