CIRCT 20.0.0git
Loading...
Searching...
No Matches
ESIModule.cpp
Go to the documentation of this file.
1//===- ESIModule.cpp - ESI API nanobind 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/NanobindAdaptors.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 "NanobindUtils.h"
24#include <nanobind/nanobind.h>
25namespace nb = nanobind;
26
27using namespace circt::esi;
28
29//===----------------------------------------------------------------------===//
30// The main entry point into the ESI Assembly API.
31//===----------------------------------------------------------------------===//
32
33/// Container for a Python function that will be called to generate a service.
35public:
36 ServiceGenFunc(nb::object genFunc) : genFunc(std::move(genFunc)) {}
37
38 MlirLogicalResult run(MlirOperation reqOp, MlirOperation declOp,
39 MlirOperation recOp) {
40 nb::gil_scoped_acquire acquire;
41 nb::object rc = genFunc(reqOp, declOp, recOp);
42 return nb::cast<bool>(rc) ? mlirLogicalResultSuccess()
43 : mlirLogicalResultFailure();
44 }
45
46private:
47 nb::object genFunc;
48};
49
50// Mapping from unique identifier to python callback. We use std::string
51// pointers since we also need to allocate memory for the string.
52llvm::DenseMap<std::string *, ServiceGenFunc> serviceGenFuncLookup;
53static MlirLogicalResult serviceGenFunc(MlirOperation reqOp,
54 MlirOperation declOp,
55 MlirOperation recOp, void *userData) {
56 std::string *name = static_cast<std::string *>(userData);
57 auto iter = serviceGenFuncLookup.find(name);
58 if (iter == serviceGenFuncLookup.end())
59 return mlirLogicalResultFailure();
60 return iter->getSecond().run(reqOp, declOp, recOp);
61}
62
63void registerServiceGenerator(std::string name, nb::object genFunc) {
64 std::string *n = new std::string(name);
65 serviceGenFuncLookup.try_emplace(n, ServiceGenFunc(genFunc));
67}
68
70public:
71 PyAppIDIndex(MlirOperation root) { index = circtESIAppIDIndexGet(root); }
72 PyAppIDIndex(const PyAppIDIndex &) = delete;
74
75 MlirAttribute getChildAppIDsOf(MlirOperation op) const {
77 }
78
79 nb::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid,
80 MlirLocation loc) const {
81 MlirAttribute path =
82 circtESIAppIDIndexGetAppIDPath(index, fromMod, appid, loc);
83 if (path.ptr == nullptr)
84 return nb::none();
85 return nb::cast(path);
86 }
87
88private:
90};
91
92using namespace mlir::python::nanobind_adaptors;
93
95 m.doc() = "ESI Python Native Extension";
97
98 // Clean up references when the module is unloaded.
99 auto cleanup = []() { serviceGenFuncLookup.clear(); };
100 m.def("cleanup", cleanup,
101 "Cleanup various references. Must be called before the module is "
102 "unloaded in order to not leak.");
103
104 m.def("registerServiceGenerator", registerServiceGenerator,
105 "Register a service generator for a given service name.",
106 nb::arg("impl_type"), nb::arg("generator"));
107
108 mlir_type_subclass(m, "ChannelType", circtESITypeIsAChannelType)
109 .def_classmethod(
110 "get",
111 [](nb::object cls, MlirType inner, uint32_t signaling = 0,
112 uint64_t dataDelay = 0) {
114 return cls(inner);
115 return cls(circtESIChannelTypeGet(inner, signaling, dataDelay));
116 },
117 nb::arg("cls"), nb::arg("inner"), nb::arg("signaling") = 0,
118 nb::arg("dataDelay") = 0)
119 .def_property_readonly(
120 "inner", [](MlirType self) { return circtESIChannelGetInner(self); })
121 .def_property_readonly(
122 "signaling",
123 [](MlirType self) { return circtESIChannelGetSignaling(self); })
124 .def_property_readonly("data_delay", [](MlirType self) {
125 return circtESIChannelGetDataDelay(self);
126 });
127
128 mlir_type_subclass(m, "AnyType", circtESITypeIsAnAnyType)
129 .def_classmethod(
130 "get",
131 [](nb::object cls, MlirContext ctxt) {
132 return cls(circtESIAnyTypeGet(ctxt));
133 },
134 nb::arg("self"), nb::arg("ctxt") = nullptr);
135
136 mlir_type_subclass(m, "ListType", circtESITypeIsAListType)
137 .def_classmethod(
138 "get",
139 [](nb::object cls, MlirType inner) {
140 return cls(circtESIListTypeGet(inner));
141 },
142 nb::arg("cls"), nb::arg("inner"))
143 .def_property_readonly("element_type", [](MlirType self) {
145 });
146
147 nb::enum_<ChannelDirection>(m, "ChannelDirection")
148 .value("TO", ChannelDirection::to)
149 .value("FROM", ChannelDirection::from);
150 mlir_type_subclass(m, "BundleType", circtESITypeIsABundleType)
151 .def_classmethod(
152 "get",
153 [](nb::object cls, std::vector<nb::tuple> channelTuples,
154 bool resettable, MlirContext ctxt) {
155 llvm::SmallVector<CirctESIBundleTypeBundleChannel, 4> channels(
156 llvm::map_range(channelTuples, [ctxt](nb::tuple t) {
157 std::string name = nb::cast<std::string>(t[0]);
159 mlirIdentifierGet(ctxt, mlirStringRefCreate(
160 name.data(), name.length())),
161 (uint32_t)nb::cast<ChannelDirection>(t[1]),
162 nb::cast<MlirType>(t[2])};
163 }));
164 return cls(circtESIBundleTypeGet(ctxt, channels.size(),
165 channels.data(), resettable));
166 },
167 nb::arg("cls"), nb::arg("channels"), nb::arg("resettable"),
168 nb::arg("ctxt") = nullptr)
169 .def_property_readonly("resettable", &circtESIBundleTypeGetResettable)
170 .def_property_readonly("channels", [](MlirType bundleType) {
171 std::vector<nb::tuple> channels;
172 size_t numChannels = circtESIBundleTypeGetNumChannels(bundleType);
173 for (size_t i = 0; i < numChannels; ++i) {
175 circtESIBundleTypeGetChannel(bundleType, i);
176 MlirStringRef name = mlirIdentifierStr(channel.name);
177 channels.push_back(nb::make_tuple(nb::str(name.data, name.length),
178 (ChannelDirection)channel.direction,
179 channel.channelType));
180 }
181 return channels;
182 });
183
184 mlir_attribute_subclass(m, "AppIDAttr", circtESIAttributeIsAnAppIDAttr)
185 .def_classmethod(
186 "get",
187 [](nb::object cls, std::string name, std::optional<uint64_t> index,
188 MlirContext ctxt) {
189 if (index.has_value())
190 return cls(circtESIAppIDAttrGet(ctxt, wrap(name), index.value()));
191 return cls(circtESIAppIDAttrGetNoIdx(ctxt, wrap(name)));
192 },
193 "Create an AppID attribute", nb::arg("cls"), nb::arg("name"),
194 nb::arg("index") = nb::none(), nb::arg("context") = nb::none())
195 .def_property_readonly("name",
196 [](MlirAttribute self) {
197 llvm::StringRef name =
199 return std::string(name.data(), name.size());
200 })
201 .def_property_readonly("index", [](MlirAttribute self) -> nb::object {
202 uint64_t index;
203 if (circtESIAppIDAttrGetIndex(self, &index))
204 return nb::cast(index);
205 return nb::none();
206 });
207
208 mlir_attribute_subclass(m, "AppIDPathAttr",
210 .def_classmethod(
211 "get",
212 [](nb::object cls, MlirAttribute root,
213 std::vector<MlirAttribute> path, MlirContext ctxt) {
214 return cls(
215 circtESIAppIDAttrPathGet(ctxt, root, path.size(), path.data()));
216 },
217 "Create an AppIDPath attribute", nb::arg("cls"), nb::arg("root"),
218 nb::arg("path"), nb::arg("context") = nb::none())
219 .def_property_readonly("root", &circtESIAppIDAttrPathGetRoot)
221 .def("__getitem__", &circtESIAppIDAttrPathGetComponent);
222
223 m.def("check_inner_type_match", &circtESICheckInnerTypeMatch,
224 "Check that two types match, allowing for AnyType in 'expected'.",
225 nb::arg("expected"), nb::arg("actual"));
226
227 nb::class_<PyAppIDIndex>(m, "AppIDIndex")
228 .def(nb::init<MlirOperation>(), nb::arg("root"))
229 .def("get_child_appids_of", &PyAppIDIndex::getChildAppIDsOf,
230 "Return a dictionary of AppIDAttrs to ArrayAttr of InnerRefAttrs "
231 "containing the relative paths to the leaf of the particular "
232 "AppIDAttr. Argument MUST be HWModuleLike.",
233 nb::arg("mod"))
234 .def("get_appid_path", &PyAppIDIndex::getAppIDPathAttr,
235 "Return an array of InnerNameRefAttrs representing the relative "
236 "path to 'appid' from 'fromMod'.",
237 nb::arg("from_mod"), nb::arg("appid"),
238 nb::arg("query_site") = nb::none());
239}
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
static MlirLogicalResult serviceGenFunc(MlirOperation reqOp, MlirOperation declOp, MlirOperation recOp, void *userData)
Definition ESIModule.cpp:53
void registerServiceGenerator(std::string name, nb::object genFunc)
Definition ESIModule.cpp:63
llvm::DenseMap< std::string *, ServiceGenFunc > serviceGenFuncLookup
Definition ESIModule.cpp:52
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:112
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrGet(MlirContext, MlirStringRef name, uint64_t index)
Definition ESI.cpp:148
MLIR_CAPI_EXPORTED bool circtESIBundleTypeGetResettable(MlirType bundle)
Definition ESI.cpp:126
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:94
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDIndexGetChildAppIDsOf(CirctESIAppIDIndex, MlirOperation)
Definition ESI.cpp:209
MLIR_CAPI_EXPORTED MlirType circtESIChannelGetInner(MlirType channelType)
Definition ESI.cpp:43
MLIR_CAPI_EXPORTED CirctESIBundleTypeBundleChannel circtESIBundleTypeGetChannel(MlirType bundle, size_t idx)
Definition ESI.cpp:132
MLIR_CAPI_EXPORTED void circtESIAppIDIndexFree(CirctESIAppIDIndex)
Free an AppIDIndex.
Definition ESI.cpp:204
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrGetNoIdx(MlirContext ctxt, MlirStringRef name)
Definition ESI.cpp:153
MLIR_CAPI_EXPORTED uint64_t circtESIAppIDAttrPathGetNumComponents(MlirAttribute attr)
Definition ESI.cpp:184
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDIndexGetAppIDPath(CirctESIAppIDIndex, MlirOperation fromMod, MlirAttribute appid, MlirLocation loc)
Definition ESI.cpp:215
MLIR_CAPI_EXPORTED MlirStringRef circtESIAppIDAttrGetName(MlirAttribute attr)
Definition ESI.cpp:157
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:129
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:187
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:172
MLIR_CAPI_EXPORTED MlirType circtESIListTypeGet(MlirType inner)
Definition ESI.cpp:64
MLIR_CAPI_EXPORTED bool circtESITypeIsABundleType(MlirType type)
Definition ESI.cpp:109
MLIR_CAPI_EXPORTED bool circtESIAppIDAttrGetIndex(MlirAttribute attr, uint64_t *index)
Definition ESI.cpp:160
MLIR_CAPI_EXPORTED bool circtESICheckInnerTypeMatch(MlirType to, MlirType from)
Definition ESI.cpp:73
MLIR_CAPI_EXPORTED MlirAttribute circtESIAppIDAttrPathGetRoot(MlirAttribute attr)
Definition ESI.cpp:181
MLIR_CAPI_EXPORTED bool circtESIAttributeIsAnAppIDPathAttr(MlirAttribute)
Definition ESI.cpp:168
MLIR_CAPI_EXPORTED CirctESIAppIDIndex circtESIAppIDIndexGet(MlirOperation root)
Create an index of appids through which to do appid lookups efficiently.
Definition ESI.cpp:196
MLIR_CAPI_EXPORTED bool circtESIAttributeIsAnAppIDAttr(MlirAttribute)
Definition ESI.cpp:144
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:89
PyAppIDIndex(MlirOperation root)
Definition ESIModule.cpp:71
nb::object getAppIDPathAttr(MlirOperation fromMod, MlirAttribute appid, MlirLocation loc) const
Definition ESIModule.cpp:79
MlirAttribute getChildAppIDsOf(MlirOperation op) const
Definition ESIModule.cpp:75
Container for a Python function that will be called to generate a service.
Definition ESIModule.cpp:34
MlirLogicalResult run(MlirOperation reqOp, MlirOperation declOp, MlirOperation recOp)
Definition ESIModule.cpp:38
nb::object genFunc
Definition ESIModule.cpp:47
ServiceGenFunc(nb::object genFunc)
Definition ESIModule.cpp:36
void registerESIPasses()
void populateDialectESISubmodule(nanobind::module_ &m)
MlirIdentifier name
Definition ESI.h:50