11#include "mlir/IR/Builders.h"
12#include "mlir/IR/DialectImplementation.h"
13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/SmallVector.h"
15#include "llvm/ADT/StringExtras.h"
16#include "llvm/ADT/TypeSwitch.h"
17#include "llvm/Support/MathExtras.h"
23#include "circt/Dialect/AXI4/AXI4Enums.cpp.inc"
25#define GET_ATTRDEF_CLASSES
26#include "circt/Dialect/AXI4/AXI4Attributes.cpp.inc"
29BurstSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,
30 BurstKind kind, uint32_t len) {
34 case BurstKind::Fixed:
35 if (len == 0 || len > 16)
36 return emitError() <<
"'fixed' burst 'len' must be between 1 and 16, got "
40 if (len == 0 || len > 256)
41 return emitError() <<
"'incr' burst 'len' must be between 1 and 256, got "
45 if (len < 2 || len > 16 || !llvm::isPowerOf2_32(len))
46 return emitError() <<
"'wrap' burst 'len' must be 2, 4, 8, or 16, got "
54bool BurstSpecAttr::compareCanonical(BurstSpecAttr lhs, BurstSpecAttr rhs) {
55 if (lhs.getKind() != rhs.getKind())
56 return lhs.getKind() < rhs.getKind();
57 return lhs.getLen() < rhs.getLen();
60LogicalResult BurstSetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
61 ArrayRef<BurstSpecAttr> burstSpecs) {
62 if (burstSpecs.empty())
63 return emitError() <<
"'burst_set' must be non-empty";
67bool BurstSetAttr::covers(BurstSetAttr other) {
69 return llvm::all_of(other.getBurstSpecs(), [&](BurstSpecAttr required) {
70 return llvm::any_of(getBurstSpecs(), [&](BurstSpecAttr spec) {
71 return spec.getKind() == required.getKind() &&
72 spec.getLen() >= required.getLen();
77LogicalResult WindowAttr::verify(function_ref<InFlightDiagnostic()> emitError,
78 uint64_t base, uint64_t last,
79 BurstSetAttr burstSpecs) {
81 return emitError() <<
"window 'last' address 0x"
82 << llvm::utohexstr(last,
true)
83 <<
" must not be less than 'base' address 0x"
84 << llvm::utohexstr(base,
true);
88bool WindowAttr::overlaps(WindowAttr other) {
89 return getBase() <= other.getLast() && other.getBase() <= getLast();
92SmallVector<WindowAttr> WindowSetAttr::normalize(MLIRContext *ctx,
93 ArrayRef<WindowAttr> windows) {
99 SmallVector<uint64_t> cuts;
100 for (WindowAttr window : windows) {
101 cuts.push_back(window.getBase());
102 if (window.getLast() != UINT64_MAX)
103 cuts.push_back(window.getLast() + 1);
106 cuts.erase(llvm::unique(cuts), cuts.end());
108 SmallVector<WindowAttr> normalized;
109 SmallVector<BurstSpecAttr> specs;
110 for (
size_t i = 0; i < cuts.size(); ++i) {
111 uint64_t lo = cuts[i];
112 uint64_t hi = i + 1 < cuts.size() ? cuts[i + 1] - 1 : UINT64_MAX;
116 for (WindowAttr window : windows)
117 if (window.getBase() <= lo && lo <= window.getLast())
118 llvm::append_range(specs, window.getBurstSpecs().getBurstSpecs());
125 auto burstSpecs = BurstSetAttr::get(ctx, specs);
129 if (!normalized.empty() && normalized.back().getLast() + 1 == lo &&
130 normalized.back().getBurstSpecs() == burstSpecs)
131 lo = normalized.pop_back_val().getBase();
132 normalized.push_back(WindowAttr::get(ctx, lo, hi, burstSpecs));
138WindowSetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
139 ArrayRef<WindowAttr> windows) {
141 return emitError() <<
"'window_set' must be non-empty";
145bool WindowSetAttr::overlaps(WindowSetAttr other) {
148 ArrayRef<WindowAttr> windows = getWindows();
149 ArrayRef<WindowAttr> otherWindows = other.getWindows();
150 for (
size_t i = 0, j = 0; i < windows.size() && j < otherWindows.size();) {
151 WindowAttr window = windows[i], otherWindow = otherWindows[j];
152 if (window.overlaps(otherWindow))
154 if (window.getLast() < otherWindow.getLast())
162void AXI4Dialect::registerAttributes() {
164#define GET_ATTRDEF_LIST
165#include "circt/Dialect/AXI4/AXI4Attributes.cpp.inc"
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.