CIRCT 23.0.0git
Loading...
Searching...
No Matches
ArcTypes.cpp
Go to the documentation of this file.
1//===- ArcTypes.cpp -------------------------------------------------------===//
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
13#include "mlir/IR/Builders.h"
14#include "mlir/IR/DialectImplementation.h"
15#include "llvm/ADT/TypeSwitch.h"
16
17using namespace circt;
18using namespace arc;
19using namespace mlir;
20
21static ParseResult parseXInDimList(AsmParser &p, Type &elementType);
22static void printXInDimList(AsmPrinter &p, Type elementType);
23
24#define GET_TYPEDEF_CLASSES
25#include "circt/Dialect/Arc/ArcTypes.cpp.inc"
26
27/// Compute the bit width a type will have when allocated as part of the
28/// simulator's storage. This includes any padding and alignment that may be
29/// necessary once the type has been mapped to LLVM. The idea is for this
30/// function to be conservative, such that we provide sufficient storage bytes
31/// for any type.
32std::optional<uint64_t> circt::arc::computeLLVMBitWidth(Type type) {
33 if (isa<seq::ClockType>(type))
34 return 1;
35
36 if (auto intType = dyn_cast<IntegerType>(type))
37 return intType.getWidth();
38
39 auto computeForArrayType = [&](auto arrayType) -> std::optional<uint64_t> {
40 // Compute element width.
41 auto maybeWidth = computeLLVMBitWidth(arrayType.getElementType());
42 if (!maybeWidth)
43 return {};
44 // Each element must be at least one byte.
45 auto width = std::max<uint64_t>(*maybeWidth, 8);
46 // Align elements to their own size, up to 16 bytes.
47 auto alignment = llvm::bit_ceil(std::min<uint64_t>(width, 16 * 8));
48 auto alignedWidth = llvm::alignToPowerOf2(width, alignment);
49 // Multiply by the number of elements in the array.
50 return arrayType.getNumElements() * alignedWidth;
51 };
52
53 if (auto arrayType = dyn_cast<hw::ArrayType>(type))
54 return computeForArrayType(arrayType);
55
56 if (auto arrayRefType = dyn_cast<ArrayRefType>(type))
57 return computeForArrayType(arrayRefType);
58
59 if (auto structType = dyn_cast<hw::StructType>(type)) {
60 uint64_t structWidth = 0;
61 uint64_t structAlignment = 8;
62 for (auto element : structType.getElements()) {
63 // Compute element width.
64 auto maybeWidth = computeLLVMBitWidth(element.type);
65 if (!maybeWidth)
66 return {};
67 // Each element must be at least one byte.
68 auto width = std::max<uint64_t>(*maybeWidth, 8);
69 // Align elements to their own size, up to 16 bytes.
70 auto alignment = llvm::bit_ceil(std::min<uint64_t>(width, 16 * 8));
71 auto alignedWidth = llvm::alignToPowerOf2(width, alignment);
72 // Pad the struct size to align the element to its alignment need, and add
73 // the element.
74 structWidth = llvm::alignToPowerOf2(structWidth, alignment);
75 structWidth += alignedWidth;
76 // Keep track of the struct's alignment need.
77 structAlignment = std::max<uint64_t>(alignment, structAlignment);
78 }
79 // Pad the struct size to align its end with the alignment.
80 return llvm::alignToPowerOf2(structWidth, structAlignment);
81 }
82
83 // We don't know anything about any other types.
84 return {};
85}
86
87unsigned StateType::getBitWidth() { return *computeLLVMBitWidth(getType()); }
88
89LogicalResult
90StateType::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
91 Type innerType) {
92 if (!computeLLVMBitWidth(innerType))
93 return emitError() << "state type must have a known bit width; got "
94 << innerType;
95 return success();
96}
97
98unsigned MemoryType::getStride() {
99 unsigned stride = (getWordType().getWidth() + 7) / 8;
100 return llvm::alignToPowerOf2(stride, llvm::bit_ceil(std::min(stride, 16U)));
101}
102
103size_t ArrayRefType::getNumElements() const { return getSize(); }
104
105std::optional<int64_t> ArrayRefType::getBitWidth() const {
106 auto elementBitWidth = hw::getBitWidth(getElementType());
107 if (elementBitWidth < 0)
108 return std::nullopt;
109 int64_t numElements = getNumElements();
110 if (numElements < 0)
111 return std::nullopt;
112 return numElements * elementBitWidth;
113}
114
115ShapedType ArrayRefType::cloneWith(std::optional<ArrayRef<int64_t>> shape,
116 Type elementType) const {
117 llvm_unreachable("ArrayRefType::cloneWith not implemented!");
118}
119
120bool ArrayRefType::hasRank() const { return true; }
121
122ArrayRef<int64_t> ArrayRefType::getShape() const {
123 const uint64_t &size = getImpl()->size;
124 return ArrayRef<int64_t>(reinterpret_cast<const int64_t *>(&size), 1);
125}
126
127static ParseResult parseXInDimList(AsmParser &p, Type &elementType) {
128 return failure(p.parseXInDimensionList() || p.parseType(elementType));
129}
130
131static void printXInDimList(AsmPrinter &p, Type elementType) {
132 p << "x" << elementType;
133}
134
135LogicalResult
136ArrayRefType::verify(llvm::function_ref<InFlightDiagnostic()> emitError,
137 Type elementType, uint64_t size) {
138 if (size == 0) {
139 return emitError() << "must have nonzero element count";
140 }
141 return success();
142}
143
144void ArcDialect::registerTypes() {
145 addTypes<
146#define GET_TYPEDEF_LIST
147#include "circt/Dialect/Arc/ArcTypes.cpp.inc"
148 >();
149}
static void printXInDimList(AsmPrinter &p, Type elementType)
Definition ArcTypes.cpp:131
static ParseResult parseXInDimList(AsmParser &p, Type &elementType)
Definition ArcTypes.cpp:127
MlirType uint64_t numElements
Definition CHIRRTL.cpp:30
MlirType elementType
Definition CHIRRTL.cpp:29
Definition arc.py:1
std::optional< uint64_t > computeLLVMBitWidth(mlir::Type type)
Compute the bit width a type will have when allocated as part of the simulator's storage.
mlir::Type innerType(mlir::Type type)
Definition ESITypes.cpp:422
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.