CIRCT 24.0.0git
Loading...
Searching...
No Matches
AXI4Attributes.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
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"
18
19using namespace circt;
20using namespace axi4;
21using namespace mlir;
22
23#include "circt/Dialect/AXI4/AXI4Enums.cpp.inc"
24
25#define GET_ATTRDEF_CLASSES
26#include "circt/Dialect/AXI4/AXI4Attributes.cpp.inc"
27
28LogicalResult
29BurstSpecAttr::verify(function_ref<InFlightDiagnostic()> emitError,
30 BurstKind kind, uint32_t len) {
31 // AXI4 permits 1-16 beats for 'fixed', 1-256 for 'incr', and only 2, 4, 8,
32 // or 16 for 'wrap'.
33 switch (kind) {
34 case BurstKind::Fixed:
35 if (len == 0 || len > 16)
36 return emitError() << "'fixed' burst 'len' must be between 1 and 16, got "
37 << len;
38 break;
39 case BurstKind::Incr:
40 if (len == 0 || len > 256)
41 return emitError() << "'incr' burst 'len' must be between 1 and 256, got "
42 << len;
43 break;
44 case BurstKind::Wrap:
45 if (len < 2 || len > 16 || !llvm::isPowerOf2_32(len))
46 return emitError() << "'wrap' burst 'len' must be 2, 4, 8, or 16, got "
47 << len;
48 break;
49 }
50 return success();
51}
52
53/// Ordering for burst_set construction
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();
58}
59
60LogicalResult BurstSetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
61 ArrayRef<BurstSpecAttr> burstSpecs) {
62 if (burstSpecs.empty())
63 return emitError() << "'burst_set' must be non-empty";
64 return success();
65}
66
67LogicalResult WindowAttr::verify(function_ref<InFlightDiagnostic()> emitError,
68 uint64_t base, uint64_t last,
69 BurstSetAttr burstSpecs) {
70 if (last < base)
71 return emitError() << "window 'last' address 0x"
72 << llvm::utohexstr(last, /*LowerCase=*/true)
73 << " must not be less than 'base' address 0x"
74 << llvm::utohexstr(base, /*LowerCase=*/true);
75 return success();
76}
77
78SmallVector<WindowAttr> WindowSetAttr::normalize(MLIRContext *ctx,
79 ArrayRef<WindowAttr> windows) {
80 // Split the address space at every point where the specs could change (i.e.
81 // the start and end points of the windows).
82 // Then, for each of those segments, accumulate all the specs that cover it,
83 // and create a window accordingly.
84
85 SmallVector<uint64_t> cuts;
86 for (WindowAttr window : windows) {
87 cuts.push_back(window.getBase());
88 if (window.getLast() != UINT64_MAX)
89 cuts.push_back(window.getLast() + 1);
90 }
91 llvm::sort(cuts);
92 cuts.erase(llvm::unique(cuts), cuts.end());
93
94 SmallVector<WindowAttr> normalized;
95 SmallVector<BurstSpecAttr> specs;
96 for (size_t i = 0; i < cuts.size(); ++i) {
97 uint64_t lo = cuts[i];
98 uint64_t hi = i + 1 < cuts.size() ? cuts[i + 1] - 1 : UINT64_MAX;
99
100 // Collect the set of specs that cover this segment
101 specs.clear();
102 for (WindowAttr window : windows)
103 if (window.getBase() <= lo && lo <= window.getLast())
104 llvm::append_range(specs, window.getBurstSpecs().getBurstSpecs());
105
106 // Nothing covers the segment - a gap between windows.
107 if (specs.empty())
108 continue;
109
110 // BurstSetAttr::get sorts and de-duplicates the union for us.
111 auto burstSpecs = BurstSetAttr::get(ctx, specs);
112
113 // Merge into the previous window where they are contiguous and share
114 // capabilities.
115 if (!normalized.empty() && normalized.back().getLast() + 1 == lo &&
116 normalized.back().getBurstSpecs() == burstSpecs)
117 lo = normalized.pop_back_val().getBase();
118 normalized.push_back(WindowAttr::get(ctx, lo, hi, burstSpecs));
119 }
120 return normalized;
121}
122
123LogicalResult
124WindowSetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
125 ArrayRef<WindowAttr> windows) {
126 if (windows.empty())
127 return emitError() << "'window_set' must be non-empty";
128 return success();
129}
130
131void AXI4Dialect::registerAttributes() {
132 addAttributes<
133#define GET_ATTRDEF_LIST
134#include "circt/Dialect/AXI4/AXI4Attributes.cpp.inc"
135 >();
136}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.