Skip to content

Commit 81cec44

Browse files
authored
Merge pull request #56 from coredac/mrrg
Construct MRRG
2 parents 5064bb8 + 62d0115 commit 81cec44

File tree

6 files changed

+176
-30
lines changed

6 files changed

+176
-30
lines changed

include/NeuraDialect/Architecture/Architecture.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ class Link : public BasicResource {
7777
Tile* dst_tile;
7878
};
7979

80+
struct PairHash {
81+
std::size_t operator()(const std::pair<int, int> &coord) const {
82+
return std::hash<int>()(coord.first) ^ (std::hash<int>()(coord.second) << 1);
83+
}
84+
};
85+
8086
/// Describes the entire CGRA architecture.
8187
class Architecture {
8288
public:
@@ -87,12 +93,16 @@ class Architecture {
8793

8894
Link* getLink(int id);
8995

90-
int getNumTiles() const { return static_cast<int>(tiles.size()); }
91-
std::vector<Tile*> getAllTiles() { return tiles; }
96+
int getNumTiles() const;
97+
std::vector<Tile*> getAllTiles() const;
98+
std::vector<Link*> getAllLinks() const;
9299

93100
private:
94-
std::vector<std::unique_ptr<Tile>> tileStorage;
95-
std::vector<Tile*> tiles;
101+
std::vector<std::unique_ptr<Tile>> tile_storage;
102+
// std::vector<Tile*> tiles;
103+
std::vector<std::unique_ptr<Link>> link_storage;
104+
std::unordered_map<int, Tile*> id_to_tile;
105+
std::unordered_map<std::pair<int, int>, Tile*, PairHash> coord_to_tile;
96106
};
97107

98108
} // namespace neura

include/NeuraDialect/Mapping/MappingState.h

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,74 @@
1111
namespace mlir {
1212
namespace neura {
1313

14-
// Represents a spatial-temporal location: (resource, timeStep)
15-
using MappingLoc = std::pair<BasicResource*, int>;
14+
// Represents a spatial-temporal location: (resource, time_step)
15+
struct MappingLoc {
16+
BasicResource* resource;
17+
int time_step;
18+
19+
bool operator==(const MappingLoc &other) const {
20+
return resource == other.resource && time_step == other.time_step;
21+
}
22+
};
23+
24+
} // namespace neura
25+
} // namespace mlir
26+
27+
namespace std {
28+
template <>
29+
struct hash<mlir::neura::MappingLoc> {
30+
std::size_t operator()(const mlir::neura::MappingLoc& loc) const {
31+
std::size_t h1 = std::hash<mlir::neura::BasicResource*>()(loc.resource);
32+
std::size_t h2 = std::hash<int>()(loc.time_step);
33+
return h1 ^ (h2 << 1);
34+
}
35+
};
36+
}
37+
38+
namespace mlir {
39+
namespace neura {
1640

1741
// Tracks placement and routing of ops on the CGRA.
1842
class MappingState {
1943
public:
20-
// Binds a (tile/link, timeStep) location to an operation.
44+
MappingState(const Architecture &arch, int II);
45+
// Binds a (tile/link, time_step) location to an operation.
2146
void bindOp(MappingLoc loc, Operation *op);
2247

23-
// Checks if a (tile/link, timeStep) is available (unoccupied).
48+
// Checks if a (tile/link, time_step) is available (unoccupied).
2449
bool isAvailable(const MappingLoc &loc) const;
2550

26-
// Gets the operation at a specific (tile/link, timeStep) location.
51+
// Gets the operation at a specific (tile/link, time_step) location.
2752
std::optional<Operation*> getOpAt(MappingLoc loc) const;
2853

54+
// Gets all MRRG nodes.
55+
const std::unordered_set<MappingLoc> &getAllLocs() const;
56+
57+
// Gets neighboring tiles on next step of a given MappingLoc.
58+
const std::vector<MappingLoc> &getNextStepTiles(MappingLoc loc) const;
59+
60+
// Gets neighboring links on next step of a given MappingLoc.
61+
const std::vector<MappingLoc> &getNextStepLinks(MappingLoc loc) const;
62+
63+
// Gets neighboring tiles on current step of a given MappingLoc.
64+
const std::vector<MappingLoc> &getCurrentStepTiles(MappingLoc loc) const;
65+
66+
// Gets neighboring links on current step of a given MappingLoc.
67+
const std::vector<MappingLoc> &getCurrentStepLinks(MappingLoc loc) const;
68+
69+
int getII() const { return II; }
70+
2971
private:
72+
// Initiation interval.
73+
int II;
74+
std::unordered_set<MappingLoc> all_locs;
75+
// current and next step tiles and links for a given MappingLoc. Note that
76+
// the key MappingLoc is either a pair of (tile, time_step) or (link, time_step).
77+
std::unordered_map<MappingLoc, std::vector<MappingLoc>> next_step_tiles;
78+
std::unordered_map<MappingLoc, std::vector<MappingLoc>> next_step_links;
79+
std::unordered_map<MappingLoc, std::vector<MappingLoc>> current_step_tiles;
80+
std::unordered_map<MappingLoc, std::vector<MappingLoc>> current_step_links;
81+
3082
std::unordered_map<MappingLoc, Operation*> loc_to_op;
3183
std::unordered_set<MappingLoc> occupied_locs;
3284
};

lib/NeuraDialect/Architecture/Architecture.cpp

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#include "NeuraDialect/Architecture/Architecture.h"
2+
#include "llvm/Support/raw_ostream.h"
3+
24
#include <cassert>
35

46
using namespace mlir;
@@ -72,14 +74,15 @@ void Link::connect(Tile* src, Tile* dst) {
7274
Architecture::Architecture(int width, int height) {
7375
const int num_tiles = width * height;
7476

75-
tileStorage.reserve(num_tiles);
76-
tiles.reserve(num_tiles);
77+
tile_storage.reserve(num_tiles);
7778

7879
for (int i = 0; i < width; ++i) {
7980
for (int j = 0; j < height; ++j) {
80-
auto tile = std::make_unique<Tile>(i * width + j, i, j);
81-
tiles.push_back(tile.get());
82-
tileStorage.push_back(std::move(tile));
81+
const int id = i * width + j;
82+
auto tile = std::make_unique<Tile>(id, i, j);
83+
id_to_tile[id] = tile.get();
84+
coord_to_tile[{i, j}] = tile.get();
85+
tile_storage.push_back(std::move(tile));
8386
}
8487
}
8588

@@ -92,39 +95,54 @@ Architecture::Architecture(int width, int height) {
9295
if (i > 0) {
9396
auto link_towards_left = std::make_unique<Link>(link_id++);
9497
link_towards_left->connect(tile, getTile(i - 1, j));
98+
link_storage.push_back(std::move(link_towards_left));
9599
}
96100
if (i < width - 1) {
97101
auto link_towards_right = std::make_unique<Link>(link_id++);
98102
link_towards_right->connect(tile, getTile(i + 1, j));
103+
link_storage.push_back(std::move(link_towards_right));
99104
}
100105
if (j > 0) {
101106
auto link_towards_down = std::make_unique<Link>(link_id++);
102107
link_towards_down->connect(tile, getTile(i, j - 1));
108+
link_storage.push_back(std::move(link_towards_down));
103109
}
104110
if (j < height - 1) {
105111
auto link_towards_up = std::make_unique<Link>(link_id++);
106112
link_towards_up->connect(tile, getTile(i, j + 1));
113+
link_storage.push_back(std::move(link_towards_up));
107114
}
108115
}
109116
}
110117
}
111118

112119
Tile* Architecture::getTile(int id) {
113-
for (const auto &tile : tiles) {
114-
if (tile->getId() == id) {
115-
return tile;
116-
}
117-
}
118-
assert(false && "Tile with given ID not found");
119-
return nullptr;
120+
auto it = id_to_tile.find(id);
121+
assert(it != id_to_tile.end() && "Tile with given ID not found");
122+
return it->second;
120123
}
121124

122125
Tile* Architecture::getTile(int x, int y) {
123-
for (const auto &tile : tiles) {
124-
if (tile->getX() == x && tile->getY() == y) {
125-
return tile;
126-
}
126+
auto it = coord_to_tile.find({x, y});
127+
assert(it != coord_to_tile.end() && "Tile with given coordinates not found");
128+
return it->second;
129+
}
130+
131+
std::vector<Tile*> Architecture::getAllTiles() const {
132+
std::vector<Tile*> result;
133+
for (auto &tile : tile_storage)
134+
result.push_back(tile.get());
135+
return result;
136+
}
137+
138+
int Architecture::getNumTiles() const {
139+
return static_cast<int>(id_to_tile.size());
140+
}
141+
142+
std::vector<Link*> Architecture::getAllLinks() const {
143+
std::vector<Link*> all_links;
144+
for (const auto &link : link_storage) {
145+
all_links.push_back(link.get());
127146
}
128-
assert(false && "Tile with given coordinates not found");
129-
return nullptr;
147+
return all_links;
130148
}

lib/NeuraDialect/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_mlir_dialect_library(MLIRNeura
2020
NeuraTypes.cpp
2121
NeuraPasses.cpp
2222
Mapping/mapping_util.cpp
23+
Mapping/MappingState.cpp
2324
Architecture/Architecture.cpp
2425

2526
ADDITIONAL_HEADER_DIRS

lib/NeuraDialect/Mapping/MappingState.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,67 @@
33
using namespace mlir;
44
using namespace mlir::neura;
55

6+
MappingState::MappingState(const Architecture &arch, int II) : II(II) {
7+
for (Tile* tile : arch.getAllTiles()) {
8+
for (int t = 0; t < II; ++t) {
9+
MappingLoc loc = {tile, t};
10+
all_locs.insert(loc);
11+
12+
// Create edges to neighboring tiles at t+1.
13+
for (Tile* dst : tile->getDstTiles()) {
14+
MappingLoc next_step_dst_tile_loc = {dst, (t + 1) % II}; // modulo II for reuse
15+
next_step_tiles[loc].push_back(next_step_dst_tile_loc);
16+
}
17+
18+
// TODO: Not sure whether we need the link on t or t+1.
19+
// Creates edges to neighboring links at t.
20+
for (Link* dst : tile->getOutLinks()) {
21+
MappingLoc current_step_dst_link_loc = {dst, t % II};
22+
next_step_tiles[loc].push_back(current_step_dst_link_loc);
23+
}
24+
}
25+
}
26+
}
27+
628
void MappingState::bindOp(MappingLoc loc, Operation *op) {
729
loc_to_op[loc] = op;
830
occupied_locs.insert(loc);
931
}
1032

1133
bool MappingState::isAvailable(const MappingLoc &loc) const {
12-
return !occupied_locs.contains(loc);
34+
return occupied_locs.find(loc) == occupied_locs.end();
35+
}
36+
37+
std::optional<Operation*> MappingState::getOpAt(MappingLoc loc) const {
38+
auto it = loc_to_op.find(loc);
39+
if (it == loc_to_op.end()) return std::nullopt;
40+
return it->second;
41+
}
42+
43+
const std::unordered_set<MappingLoc> &MappingState::getAllLocs() const {
44+
return all_locs;
1345
}
46+
47+
const std::vector<MappingLoc> &MappingState::getNextStepTiles(MappingLoc loc) const {
48+
static const std::vector<MappingLoc> empty;
49+
auto it = next_step_tiles.find(loc);
50+
return it != next_step_tiles.end() ? it->second : empty;
51+
}
52+
53+
const std::vector<MappingLoc> &MappingState::getNextStepLinks(MappingLoc loc) const {
54+
static const std::vector<MappingLoc> empty;
55+
auto it = next_step_links.find(loc);
56+
return it != next_step_links.end() ? it->second : empty;
57+
}
58+
59+
const std::vector<MappingLoc> &MappingState::getCurrentStepTiles(MappingLoc loc) const {
60+
static const std::vector<MappingLoc> empty;
61+
auto it = current_step_tiles.find(loc);
62+
return it != current_step_tiles.end() ? it->second : empty;
63+
}
64+
65+
const std::vector<MappingLoc> &MappingState::getCurrentStepLinks(MappingLoc loc) const {
66+
static const std::vector<MappingLoc> empty;
67+
auto it = current_step_links.find(loc);
68+
return it != current_step_links.end() ? it->second : empty;
69+
}

lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "NeuraDialect/NeuraOps.h"
66
#include "NeuraDialect/NeuraTypes.h"
77
#include "NeuraDialect/NeuraPasses.h"
8+
#include "NeuraDialect/Mapping/MappingState.h"
89
#include "NeuraDialect/Mapping/mapping_util.h"
910
#include "mlir/Dialect/Func/IR/FuncOps.h"
1011
#include "mlir/IR/PatternMatch.h"
@@ -44,6 +45,7 @@ struct MapToAcceleratorPass
4445
// Collects and reports recurrence cycles found in the function.
4546
auto recurrence_cycles = collectRecurrenceCycles(func);
4647
RecurrenceCycle *longest = nullptr;
48+
int rec_mii = 1;
4749
for (auto &cycle : recurrence_cycles) {
4850
if (!longest || cycle.length > longest->length)
4951
longest = &cycle;
@@ -52,10 +54,12 @@ struct MapToAcceleratorPass
5254
if (longest) {
5355
llvm::errs() << "[MapToAcceleratorPass] Longest recurrence cycle (length "
5456
<< longest->length << "):\n";
55-
for (Operation *op : longest->operations)
57+
for (Operation *op : longest->operations) {
5658
op->print(llvm::errs()), llvm::errs() << "\n";
59+
}
60+
rec_mii = longest->length;
5761
IntegerAttr rec_mii_attr = IntegerAttr::get(
58-
IntegerType::get(func.getContext(), 32), longest->length);
62+
IntegerType::get(func.getContext(), 32), rec_mii);
5963
func->setAttr("RecMII", rec_mii_attr);
6064
}
6165

@@ -66,6 +70,11 @@ struct MapToAcceleratorPass
6670
IntegerType::get(func.getContext(), 32), res_mii);
6771
func->setAttr("ResMII", res_mii_attr);
6872

73+
const int minII = std::min(rec_mii, res_mii);
74+
constexpr int maxII = 5;
75+
for (int ii = minII; ii <= maxII; ++ii) {
76+
MappingState state(architecture, ii);
77+
}
6978
});
7079
}
7180
};

0 commit comments

Comments
 (0)