diff --git a/include/NeuraDialect/Architecture/Architecture.h b/include/NeuraDialect/Architecture/Architecture.h index 8d7028cf..ca7a4951 100644 --- a/include/NeuraDialect/Architecture/Architecture.h +++ b/include/NeuraDialect/Architecture/Architecture.h @@ -367,22 +367,31 @@ struct LinkOverride; class Architecture { public: // Single constructor - handles all cases internally. - Architecture(int width, int height, - const TileDefaults& tile_defaults, - const std::vector& tile_overrides, - const LinkDefaults& link_defaults, - const std::vector& link_overrides, - BaseTopology base_topology = BaseTopology::MESH); + Architecture(int multi_cgra_rows, + int multi_cgra_columns, + BaseTopology multi_cgra_base_topology = BaseTopology::MESH, + int per_cgra_rows = 4, + int per_cgra_columns = 4, + BaseTopology per_cgra_base_topology = BaseTopology::MESH, + const TileDefaults& tile_defaults = TileDefaults(), + const std::vector& tile_overrides = std::vector(), + const LinkDefaults& link_defaults = LinkDefaults(), + const std::vector& link_overrides = std::vector()); Tile *getTile(int id); Tile *getTile(int x, int y); - int getWidth() const { return width; } - int getHeight() const { return height; } + int getMultiCgraRows() const { return multi_cgra_rows_; } + int getMultiCgraColumns() const { return multi_cgra_columns_; } + int getPerCgraRows() const { return per_cgra_rows_; } + int getPerCgraColumns() const { return per_cgra_columns_; } Link *getLink(int id); + Link *getLink(int src_tile_x, int src_tile_y, int dst_tile_x, int dst_tile_y); void removeLink(int link_id); - + void removeLink(Tile *src_tile, Tile *dst_tile); + void removeLink(int src_tile_x, int src_tile_y, int dst_tile_x, int dst_tile_y); + // Tile management. void removeTile(int tile_id); @@ -392,7 +401,7 @@ class Architecture { private: // Helper methods for constructor initialization. - void initializeTiles(int width, int height); + void initializeTiles(int rows, int columns); void configureDefaultTileSettings(const TileDefaults& tile_defaults); void applyTileOverrides(const std::vector& tile_overrides); void createLinks(const LinkDefaults& link_defaults, BaseTopology base_topology); @@ -410,13 +419,15 @@ class Architecture { // Architecture components: tiles, links, and their mappings. // Ports and memory are now modeled as part of Tile class. - std::map> tile_storage; // Owns tiles, key is unique tile_id. - std::map> link_storage; // Owns links, key is unique link_id. - std::unordered_map id_to_tile; // Maps unique tile_id to Tile pointer. - std::unordered_map, Tile *, PairHash> coord_to_tile; // Maps (x,y) coordinates to Tile pointer. - - int width; - int height; + std::map> tile_storage_; // Owns tiles, key is unique tile_id. + std::map> link_storage_; // Owns links, key is unique link_id. + std::unordered_map id_to_tile_; // Maps unique tile_id to Tile pointer. + std::unordered_map, Tile *, PairHash> coord_to_tile_; // Maps (x,y) coordinates to Tile pointer. + + int multi_cgra_rows_; + int multi_cgra_columns_; + int per_cgra_rows_; + int per_cgra_columns_; }; } // namespace neura diff --git a/include/NeuraDialect/Architecture/ArchitectureSpec.h b/include/NeuraDialect/Architecture/ArchitectureSpec.h index 9e8d79be..8e47bdfb 100644 --- a/include/NeuraDialect/Architecture/ArchitectureSpec.h +++ b/include/NeuraDialect/Architecture/ArchitectureSpec.h @@ -17,34 +17,63 @@ enum class BaseTopology { // Structure for holding tile default configuration. struct TileDefaults { int num_registers = 64; // default value. - std::vector default_ports = {"N", "S", "W", "E"}; // default ports. std::vector operations = { - "add", "mul", "sub", "div", "rem", - "fadd", "fmul", "fsub", "fdiv", - "or", "not", "icmp", "fcmp", "sel", - "cast", "sext", "zext", "shl", - "vfmul", "fadd_fadd", "fmul_fadd", - "data_mov", "ctrl_mov", - "reserve", "grant_predicate", "grant_once", "grant_always", - "loop_control", "phi", "constant", - "load", "store", "return", - "load_indexed", "store_indexed", "alloca" + "add", + "mul", + "sub", + "div", + "rem", + "fadd", + "fmul", + "fsub", + "fdiv", + "or", + "not", + "icmp", + "fcmp", + "sel", + "cast", + "sext", + "zext", + "shl", + "vfmul", + "fadd_fadd", + "fmul_fadd", + "data_mov", + "ctrl_mov", + "reserve", + "grant_predicate", + "grant_once", + "grant_always", + "loop_control", + "phi", + "constant", + "load", + "store", + "return", + "load_indexed", + "store_indexed", + "alloca" }; // default operations - includes all supported operations for newbie convenience. }; // Structure for holding memory configuration. struct MemoryConfig { - int capacity = -1; // Memory capacity in bytes. + int capacity = 1024; // Memory capacity in bytes. + int banks_per_cgra = 4; // Number of banks per CGRA. }; // Structure for holding tile override configuration. struct TileOverride { - int id = -1; - int x = -1, y = -1; + // CGRA coordinates. + int cgra_x = -1; + int cgra_y = -1; + // Tile coordinates within per-CGRA. + int tile_x = -1; + int tile_y = -1; std::vector operations; - int num_registers = -1; - std::vector ports; - MemoryConfig memory; + int num_registers = 4; + bool existence = true; }; // Structure for holding link default configuration. @@ -55,11 +84,16 @@ struct LinkDefaults { // Structure for holding link override configuration. struct LinkOverride { - int id = -1; - int latency = -1; + int latency = 1; int bandwidth = -1; - int src_tile_id = -1; - int dst_tile_id = -1; + int src_cgra_x = -1; + int src_cgra_y = -1; + int dst_cgra_x = -1; + int dst_cgra_y = -1; + int src_tile_x = -1; + int src_tile_y = -1; + int dst_tile_x = -1; + int dst_tile_y = -1; bool existence = true; }; diff --git a/include/NeuraDialect/Util/NeuraYamlKeys.h b/include/NeuraDialect/Util/NeuraYamlKeys.h new file mode 100644 index 00000000..6ded288c --- /dev/null +++ b/include/NeuraDialect/Util/NeuraYamlKeys.h @@ -0,0 +1,40 @@ +#pragma once + +#include "llvm/ADT/StringRef.h" + +namespace mlir { +namespace neura { +namespace yamlkeys { + +constexpr llvm::StringLiteral kArchitecture = "architecture"; +constexpr llvm::StringLiteral kMultiCgraDefaults = "multi_cgra_defaults"; +constexpr llvm::StringLiteral kPerCgraDefaults = "per_cgra_defaults"; +constexpr llvm::StringLiteral kTileDefaults = "tile_defaults"; +constexpr llvm::StringLiteral kTileOverrides = "tile_overrides"; +constexpr llvm::StringLiteral kLinkDefaults = "link_defaults"; +constexpr llvm::StringLiteral kLinkOverrides = "link_overrides"; +constexpr llvm::StringLiteral kOperations = "operations"; +constexpr llvm::StringLiteral kNumRegisters = "num_registers"; +constexpr llvm::StringLiteral kLatency = "latency"; +constexpr llvm::StringLiteral kBandwidth = "bandwidth"; +constexpr llvm::StringLiteral kExistence = "existence"; +constexpr llvm::StringLiteral kRows = "rows"; +constexpr llvm::StringLiteral kColumns = "columns"; +constexpr llvm::StringLiteral kBaseTopology = "base_topology"; +constexpr llvm::StringLiteral kCtrlMemItems = "ctrl_mem_items"; +constexpr llvm::StringLiteral kTileX = "tile_x"; +constexpr llvm::StringLiteral kTileY = "tile_y"; +constexpr llvm::StringLiteral kCgraX = "cgra_x"; +constexpr llvm::StringLiteral kCgraY = "cgra_y"; +constexpr llvm::StringLiteral kSrcTileX = "src_tile_x"; +constexpr llvm::StringLiteral kSrcTileY = "src_tile_y"; +constexpr llvm::StringLiteral kDstTileX = "dst_tile_x"; +constexpr llvm::StringLiteral kDstTileY = "dst_tile_y"; +constexpr llvm::StringLiteral kMesh = "mesh"; +constexpr llvm::StringLiteral kKingMesh = "king_mesh"; +constexpr llvm::StringLiteral kKingMeshAlt = "king mesh"; +constexpr llvm::StringLiteral kRing = "ring"; + +} // namespace yamlkeys +} // namespace neura +} // namespace mlir diff --git a/lib/NeuraDialect/Architecture/Architecture.cpp b/lib/NeuraDialect/Architecture/Architecture.cpp index 19ce87ed..26c5ebd1 100644 --- a/lib/NeuraDialect/Architecture/Architecture.cpp +++ b/lib/NeuraDialect/Architecture/Architecture.cpp @@ -324,14 +324,14 @@ RegisterFileCluster::getRegisterFiles() const { //===----------------------------------------------------------------------===// // Initializes tiles in the architecture. -void Architecture::initializeTiles(int width, int height) { - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - const int id = y * width + x; +void Architecture::initializeTiles(int per_cgra_rows, int per_cgra_columns) { + for (int y = 0; y < per_cgra_rows; ++y) { + for (int x = 0; x < per_cgra_columns; ++x) { + const int id = y * per_cgra_columns + x; auto tile = std::make_unique(id, x, y); - id_to_tile[id] = tile.get(); - coord_to_tile[{x, y}] = tile.get(); - tile_storage[id] = std::move(tile); + id_to_tile_[id] = tile.get(); + coord_to_tile_[{x, y}] = tile.get(); + tile_storage_[id] = std::move(tile); } } } @@ -359,8 +359,8 @@ void Architecture::createRegisterFileCluster(Tile *tile, int num_registers, int // Configures default tile settings. void Architecture::configureDefaultTileSettings(const TileDefaults& tile_defaults) { int reg_id = 0; - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { + for (int y = 0; y < getPerCgraRows(); ++y) { + for (int x = 0; x < getPerCgraColumns(); ++x) { Tile *tile = getTile(x, y); // Creates register file cluster with default capacity. @@ -368,18 +368,15 @@ void Architecture::configureDefaultTileSettings(const TileDefaults& tile_default // Configures function units based on tile_defaults.operations. configureTileFunctionUnits(tile, tile_defaults.operations); - - // Sets default ports for the tile. - tile->setPorts(tile_defaults.default_ports); } } } // Recreates register file cluster with new capacity. void Architecture::recreateRegisterFileCluster(Tile *tile, int num_registers) { - const int k_num_regs_per_regfile = 8; // Keep this fixed for now. - const int k_num_regfiles_per_cluster = num_registers / k_num_regs_per_regfile; - + constexpr int kNumRegsPerRegfile = 8; // Keep this fixed for now. + const int kNumRegfilesPerCluster = num_registers / kNumRegsPerRegfile; + // Removes existing register file cluster. if (tile->getRegisterFileCluster()) { delete tile->getRegisterFileCluster(); @@ -391,9 +388,9 @@ void Architecture::recreateRegisterFileCluster(Tile *tile, int num_registers) { // Creates registers with new capacity. int reg_id = tile->getId() * 1000; // Use tile ID as base to avoid conflicts. - for (int file_idx = 0; file_idx < k_num_regfiles_per_cluster; ++file_idx) { + for (int file_idx = 0; file_idx < kNumRegfilesPerCluster; ++file_idx) { RegisterFile *register_file = new RegisterFile(file_idx); - for (int reg_idx = 0; reg_idx < k_num_regs_per_regfile; ++reg_idx) { + for (int reg_idx = 0; reg_idx < kNumRegsPerRegfile; ++reg_idx) { Register *reg = new Register(reg_id++); register_file->addRegister(reg); } @@ -408,10 +405,8 @@ void Architecture::recreateRegisterFileCluster(Tile *tile, int num_registers) { void Architecture::applyTileOverrides(const std::vector& tile_overrides) { for (const auto &override : tile_overrides) { Tile *tile = nullptr; - if (override.id >= 0) { - tile = getTile(override.id); - } else if (override.x >= 0 && override.y >= 0) { - tile = getTile(override.x, override.y); + if (override.tile_x >= 0 && override.tile_y >= 0) { + tile = getTile(override.tile_x, override.tile_y); } if (tile) { @@ -424,16 +419,6 @@ void Architecture::applyTileOverrides(const std::vector& tile_over if (override.num_registers > 0) { recreateRegisterFileCluster(tile, override.num_registers); } - - // Overrides ports if specified. - if (!override.ports.empty()) { - tile->setPorts(override.ports); - } - - // Overrides memory capacity if specified. - if (override.memory.capacity > 0) { - tile->setMemoryCapacity(override.memory.capacity); - } } } } @@ -445,7 +430,7 @@ void Architecture::createSingleLink(int &link_id, Tile *src_tile, Tile *dst_tile link->setLatency(link_defaults.latency); link->setBandwidth(link_defaults.bandwidth); link->connect(src_tile, dst_tile); - link_storage[link_id] = std::move(link); + link_storage_[link_id] = std::move(link); link_id++; } @@ -471,22 +456,22 @@ void Architecture::createLinks(const LinkDefaults& link_defaults, BaseTopology b } // Checks if a tile is on the boundary of the architecture. -bool isOnBoundary(int x, int y, int width, int height) { - return (x == 0 || x == width - 1 || y == 0 || y == height - 1); +bool isTileOnBoundary(int x, int y, int rows, int columns) { + return (x == 0 || x == columns - 1 || y == 0 || y == rows - 1); } // Creates a link if the destination tile exists within bounds. void Architecture::createLinkIfValid(int &link_id, Tile *src_tile, int dst_x, int dst_y, const LinkDefaults& link_defaults) { - if (dst_x >= 0 && dst_x < width && dst_y >= 0 && dst_y < height) { + if (dst_x >= 0 && dst_x < getPerCgraColumns() && dst_y >= 0 && dst_y < getPerCgraRows()) { createSingleLink(link_id, src_tile, getTile(dst_x, dst_y), link_defaults); } } // Creates 4-connected mesh links (N, S, W, E). void Architecture::createMeshLinks(int &link_id, const LinkDefaults& link_defaults) { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { + for (int j = 0; j < getPerCgraRows(); ++j) { + for (int i = 0; i < getPerCgraColumns(); ++i) { Tile *tile = getTile(i, j); // Creates links to neighboring tiles with default properties. @@ -500,8 +485,8 @@ void Architecture::createMeshLinks(int &link_id, const LinkDefaults& link_defaul // Creates 8-connected king mesh links (N, S, W, E, NE, NW, SE, SW). void Architecture::createKingMeshLinks(int &link_id, const LinkDefaults& link_defaults) { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { + for (int j = 0; j < getPerCgraRows(); ++j) { + for (int i = 0; i < getPerCgraColumns(); ++i) { Tile *tile = getTile(i, j); // Creates 4-connected links (N, S, W, E). @@ -522,12 +507,12 @@ void Architecture::createKingMeshLinks(int &link_id, const LinkDefaults& link_de // Creates ring topology links (only outer boundary connections). void Architecture::createRingLinks(int &link_id, const LinkDefaults& link_defaults) { // Connects tiles on the outer boundary only. - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { + for (int j = 0; j < getPerCgraRows(); ++j) { + for (int i = 0; i < getPerCgraColumns(); ++i) { Tile *tile = getTile(i, j); // Checks if tile is on the boundary. - if (isOnBoundary(i, j, width, height)) { + if (isTileOnBoundary(i, j, getPerCgraColumns(), getPerCgraRows())) { // Creates connections only to adjacent boundary tiles. createLinkIfValid(link_id, tile, i - 1, j, link_defaults); // West createLinkIfValid(link_id, tile, i + 1, j, link_defaults); // East @@ -540,7 +525,7 @@ void Architecture::createRingLinks(int &link_id, const LinkDefaults& link_defaul // Checks if a link already exists between two tiles. bool Architecture::linkExists(Tile *src_tile, Tile *dst_tile) { - for (const auto &[id, link] : link_storage) { + for (const auto &[id, link] : link_storage_) { if (link && link->getSrcTile() == src_tile && link->getDstTile() == dst_tile) { return true; } @@ -550,31 +535,35 @@ bool Architecture::linkExists(Tile *src_tile, Tile *dst_tile) { // Applies link overrides to create, modify, or remove links. void Architecture::applyLinkOverrides(const std::vector& link_overrides) { - int next_link_id = link_storage.empty() ? 0 : link_storage.rbegin()->first + 1; // Starts from the next available ID. + int next_link_id = link_storage_.empty() ? 0 : link_storage_.rbegin()->first + 1; // Starts from the next available ID. for (const auto &override : link_overrides) { - // Handles existing link modifications/removals by ID. - if (override.id >= 0 && link_storage.find(override.id) != link_storage.end()) { - Link *link = link_storage[override.id].get(); - if (link) { - if (override.latency > 0) { - link->setLatency(override.latency); - } - - if (override.bandwidth > 0) { - link->setBandwidth(override.bandwidth); - } - - if (!override.existence) { - removeLink(override.id); - } + // TODO: Recognize the CGRA coordinates for multi-cgra when manipulate the link: + // https://github.com/coredac/dataflow/issues/163. + + // Handles existing link modifications/removals by coordinates of src/dst tiles. + Link *link = getLink(override.src_tile_x, override.src_tile_y, + override.dst_tile_x, override.dst_tile_y); + // Handles link creation and override. + if (link) { + if (override.latency > 0) { + link->setLatency(override.latency); + } + + if (override.bandwidth > 0) { + link->setBandwidth(override.bandwidth); } - } - // Handles link creation/removal by tile IDs. - else if (override.src_tile_id >= 0 && override.dst_tile_id >= 0) { - Tile *src_tile = getTile(override.src_tile_id); - Tile *dst_tile = getTile(override.dst_tile_id); + if (!override.existence) { + removeLink(override.src_tile_x, override.src_tile_y, + override.dst_tile_x, override.dst_tile_y); + } + } + // Handles link removal. + else { + Tile *src_tile = getTile(override.src_tile_x, override.src_tile_y); + Tile *dst_tile = getTile(override.dst_tile_x, override.dst_tile_y); + if (src_tile && dst_tile) { bool link_already_exists = linkExists(src_tile, dst_tile); @@ -592,18 +581,11 @@ void Architecture::applyLinkOverrides(const std::vector& link_over // Connects the tiles. link->connect(src_tile, dst_tile); - link_storage[next_link_id] = std::move(link); + link_storage_[next_link_id] = std::move(link); next_link_id++; } else if (!override.existence && link_already_exists) { - // Removes existing link. - for (auto it = link_storage.begin(); it != link_storage.end(); ++it) { - if (it->second && - it->second->getSrcTile() == src_tile && - it->second->getDstTile() == dst_tile) { - removeLink(it->first); - break; - } - } + removeLink(override.src_tile_x, override.src_tile_y, + override.dst_tile_x, override.dst_tile_y); } } } @@ -611,39 +593,47 @@ void Architecture::applyLinkOverrides(const std::vector& link_over } // Main constructor - handles all cases internally. -Architecture::Architecture(int width, int height, - const TileDefaults& tile_defaults, - const std::vector& tile_overrides, - const LinkDefaults& link_defaults, - const std::vector& link_overrides, - BaseTopology base_topology) { - this->width = width; - this->height = height; +Architecture::Architecture(int multi_cgra_rows, + int multi_cgra_columns, + BaseTopology multi_cgra_base_topology, + int per_cgra_rows, + int per_cgra_columns, + BaseTopology per_cgra_base_topology, + const TileDefaults& tile_defaults, + const std::vector& tile_overrides, + const LinkDefaults& link_defaults, + const std::vector& link_overrides) { + this->multi_cgra_rows_ = multi_cgra_rows; + this->multi_cgra_columns_ = multi_cgra_columns; + // TODO: Support multi-CGRA topology in the future: + // https://github.com/coredac/dataflow/issues/163. + // this->multi_cgra_base_topology_ = multi_cgra_base_topology; + this->per_cgra_rows_ = per_cgra_rows; + this->per_cgra_columns_ = per_cgra_columns; // Initializes architecture components using helper methods. - initializeTiles(width, height); + initializeTiles(per_cgra_rows, per_cgra_columns); configureDefaultTileSettings(tile_defaults); applyTileOverrides(tile_overrides); - createLinks(link_defaults, base_topology); + createLinks(link_defaults, per_cgra_base_topology); applyLinkOverrides(link_overrides); } - Tile *Architecture::getTile(int id) { - auto it = id_to_tile.find(id); - assert(it != id_to_tile.end() && "Tile with given ID not found"); + auto it = id_to_tile_.find(id); + assert(it != id_to_tile_.end() && "Tile with given ID not found"); return it->second; } Tile *Architecture::getTile(int x, int y) { - auto it = coord_to_tile.find({x, y}); - assert(it != coord_to_tile.end() && "Tile with given coordinates not found"); + auto it = coord_to_tile_.find({x, y}); + assert(it != coord_to_tile_.end() && "Tile with given coordinates not found"); return it->second; } std::vector Architecture::getAllTiles() const { std::vector result; - for (const auto &[id, tile] : tile_storage) { + for (const auto &[id, tile] : tile_storage_) { if (tile) { result.push_back(tile.get()); } @@ -652,13 +642,13 @@ std::vector Architecture::getAllTiles() const { } int Architecture::getNumTiles() const { - return static_cast(id_to_tile.size()); + return static_cast(id_to_tile_.size()); } // Removes a tile from the architecture. void Architecture::removeTile(int tile_id) { - auto it = tile_storage.find(tile_id); - if (it == tile_storage.end() || !it->second) { + auto it = tile_storage_.find(tile_id); + if (it == tile_storage_.end() || !it->second) { return; // Tile not found or already removed. } @@ -666,7 +656,7 @@ void Architecture::removeTile(int tile_id) { // Removes all links connected to this tile. std::vector links_to_remove; - for (const auto &[link_id, link] : link_storage) { + for (const auto &[link_id, link] : link_storage_) { if (link && (link->getSrcTile() == tile || link->getDstTile() == tile)) { links_to_remove.push_back(link_id); } @@ -677,18 +667,33 @@ void Architecture::removeTile(int tile_id) { } // Removes tile from coordinate mapping. - coord_to_tile.erase({tile->getX(), tile->getY()}); + coord_to_tile_.erase({tile->getX(), tile->getY()}); // Removes tile from ID mapping. - id_to_tile.erase(tile_id); + id_to_tile_.erase(tile_id); // Removes tile from storage. - tile_storage.erase(it); + tile_storage_.erase(it); +} + +Link *Architecture::getLink(int src_tile_x, int src_tile_y, int dst_tile_x, int dst_tile_y) { + Tile *src_tile = getTile(src_tile_x, src_tile_y); + Tile *dst_tile = getTile(dst_tile_x, dst_tile_y); + if (!src_tile || !dst_tile) { + return nullptr; // One of the tiles does not exist. + } + + for (const auto &[id, link] : link_storage_) { + if (link && link->getSrcTile() == src_tile && link->getDstTile() == dst_tile) { + return link.get(); + } + } + return nullptr; } std::vector Architecture::getAllLinks() const { std::vector all_links; - for (const auto &[id, link] : link_storage) { + for (const auto &[id, link] : link_storage_) { if (link) { all_links.push_back(link.get()); } @@ -697,8 +702,8 @@ std::vector Architecture::getAllLinks() const { } void Architecture::removeLink(int link_id) { - auto it = link_storage.find(link_id); - if (it == link_storage.end() || !it->second) { + auto it = link_storage_.find(link_id); + if (it == link_storage_.end() || !it->second) { return; } @@ -712,5 +717,32 @@ void Architecture::removeLink(int link_id) { } // Removes the link from storage. - link_storage.erase(it); + link_storage_.erase(it); +} + +void Architecture::removeLink(Tile *src_tile, Tile *dst_tile) { + + Link *link = nullptr; + for (auto it = link_storage_.begin(); it != link_storage_.end(); ++it) { + if (it->second && it->second->getSrcTile() == src_tile && it->second->getDstTile() == dst_tile) { + link = it->second.get(); + break; + } + } + + if (link) { + // Removes the link from both tiles' connection sets. + src_tile->unlinkDstTile(link, dst_tile); + // Removes the link from storage. + link_storage_.erase(link->getId()); + } } + +void Architecture::removeLink(int src_tile_x, int src_tile_y, int dst_tile_x, int dst_tile_y) { + Tile *src_tile = getTile(src_tile_x, src_tile_y); + Tile *dst_tile = getTile(dst_tile_x, dst_tile_y); + if (!src_tile || !dst_tile) { + return; // One of the tiles does not exist. + } + removeLink(src_tile, dst_tile); +} \ No newline at end of file diff --git a/lib/NeuraDialect/Mapping/mapping_util.cpp b/lib/NeuraDialect/Mapping/mapping_util.cpp index 0d59baf6..18b2a899 100644 --- a/lib/NeuraDialect/Mapping/mapping_util.cpp +++ b/lib/NeuraDialect/Mapping/mapping_util.cpp @@ -824,8 +824,8 @@ mlir::neura::calculateAward(Operation *op, std::set &critical_ops, for (Tile *tile : architecture.getAllTiles()) { if (!tile->canSupportOperation(getOperationKindFromMlirOp(op))) { - llvm::errs() << "[calculateAward] Tile: " << tile->getType() - << " does not support operation: " << *op << "\n"; + llvm::errs() << "[calculateAward] Tile<" << tile->getX() << ", " << tile->getY() + << "> does not support operation: " << *op << "\n"; continue; // Skip tiles that cannot support the operation. } int earliest_start_time_step = target_level; diff --git a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp index 2f6f6673..f0a5e8bd 100644 --- a/lib/NeuraDialect/Transforms/GenerateCodePass.cpp +++ b/lib/NeuraDialect/Transforms/GenerateCodePass.cpp @@ -162,9 +162,9 @@ struct Topology { DenseMap> tile_location; // tileId -> (x,y). DenseMap, int> coord_to_tile; // (x,y) -> tileId. - StringRef getDirBetween(int srcTid, int dstTid) const { - auto [src_x, src_y] = tile_location.lookup(srcTid); - auto [dst_x, dst_y] = tile_location.lookup(dstTid); + StringRef getDirBetween(int src_tile_id, int dst_tile_id) const { + auto [src_x, src_y] = tile_location.lookup(src_tile_id); + auto [dst_x, dst_y] = tile_location.lookup(dst_tile_id); int dc = dst_x - src_x, dr = dst_y - src_y; if (dc == 1 && dr == 0) return "EAST"; if (dc == -1 && dr == 0) return "WEST"; @@ -192,19 +192,24 @@ struct Topology { } }; -static Topology getTopologyFromArchitecture(int columns, int rows) { +static Topology getTopologyFromArchitecture(int per_cgra_rows, int per_cgra_columns) { Topology topo; - mlir::neura::Architecture arch(columns, rows, mlir::neura::TileDefaults{}, - std::vector{}, - mlir::neura::LinkDefaults{}, - std::vector{}, - mlir::neura::BaseTopology::MESH); - - for (auto *tile : arch.getAllTiles()) { + mlir::neura::Architecture architecture(1, + 1, + mlir::neura::BaseTopology::MESH, + per_cgra_rows, + per_cgra_columns, + mlir::neura::BaseTopology::MESH, + mlir::neura::TileDefaults{}, + std::vector{}, + mlir::neura::LinkDefaults{}, + std::vector{}); + + for (auto *tile : architecture.getAllTiles()) { topo.tile_location[tile->getId()] = {tile->getX(), tile->getY()}; topo.coord_to_tile[{tile->getX(), tile->getY()}] = tile->getId(); } - for (auto *link : arch.getAllLinks()) { + for (auto *link : architecture.getAllLinks()) { auto *src_tile = link->getSrcTile(); auto *dst_tile = link->getDstTile(); topo.link_ends[link->getId()] = {src_tile->getId(), dst_tile->getId()}; diff --git a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp index ce722ccc..cd9284ab 100644 --- a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp +++ b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp @@ -11,6 +11,7 @@ #include "NeuraDialect/NeuraOps.h" #include "NeuraDialect/NeuraPasses.h" #include "NeuraDialect/NeuraTypes.h" +#include "NeuraDialect/Util/NeuraYamlKeys.h" #include "mlir/Dialect/Func/IR/FuncOps.h" #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/PatternMatch.h" @@ -24,288 +25,118 @@ using namespace mlir; using namespace mlir::neura; +using namespace mlir::neura::yamlkeys; #define GEN_PASS_DEF_MAPTOACCELERATOR #include "NeuraDialect/NeuraPasses.h.inc" -// Use the TileOverride from ArchitectureSpec.h +// ----------------------------------------------------------------------------- +// Utility: Extracts an integer from a YAML ScalarNode. Returns true on success. +static bool parseYamlScalarInt(const llvm::yaml::Node *node, int &result) { + auto *scalar = llvm::dyn_cast_or_null(node); + if (!scalar) return false; + llvm::SmallString<64> value_string; + llvm::StringRef value_ref = scalar->getValue(value_string); + long long temp_value = 0; + if (value_ref.getAsInteger(10, temp_value)) return false; + result = static_cast(temp_value); + return true; +} + +// Utility: Extracts a string from a YAML ScalarNode. Returns true on success. +static bool parseYamlScalarString(const llvm::yaml::Node *node, std::string &result) { + auto *scalar = llvm::dyn_cast_or_null(node); + if (!scalar) return false; + llvm::SmallString<64> value_string; + llvm::StringRef value_ref = scalar->getValue(value_string); + result = value_ref.str(); + return true; +} +// Utility: Extracts a vector of strings from a YAML SequenceNode. +static void parseYamlStringSequence(llvm::yaml::Node *node, std::vector &result) { + auto *seq = llvm::dyn_cast_or_null(node); + if (!seq) return; + result.clear(); + for (auto &item : *seq) { + std::string value; + if (parseYamlScalarString(&item, value)) + result.push_back(value); + } +} + +// Utility: Print YAML parse error and return false. +static bool yamlParseError(const std::string &msg, const std::string &file = "") { + llvm::errs() << "[MapToAcceleratorPass] YAML parse error"; + if (!file.empty()) llvm::errs() << " in: " << file; + llvm::errs() << ": " << msg << "\n"; + return false; +} + +// ----------------------------------------------------------------------------- // Helper function to parse tile defaults. -bool parseTileDefaults(llvm::yaml::MappingNode *tile_defaults_map, mlir::neura::TileDefaults &tile_defaults) { +void parseTileDefaults(llvm::yaml::MappingNode *tile_defaults_map, mlir::neura::TileDefaults &tile_defaults) { for (auto &key_value_pair : *tile_defaults_map) { auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); if (!key_node) continue; - llvm::SmallString<64> key_string; llvm::StringRef key_ref = key_node->getValue(key_string); - - if (key_ref == "num_registers") { - auto *value_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (value_node) { - llvm::SmallString<64> value_string; - llvm::StringRef value_ref = value_node->getValue(value_string); - long long temp_value = 0; - if (!value_ref.getAsInteger(10, temp_value)) { - tile_defaults.num_registers = static_cast(temp_value); - } - } - } else if (key_ref == "operations") { - auto *value_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (value_node) { - tile_defaults.operations.clear(); - for (auto &operation_node : *value_node) { - auto *operation_scalar = llvm::dyn_cast_or_null(&operation_node); - if (operation_scalar) { - llvm::SmallString<64> operation_string; - llvm::StringRef operation_ref = operation_scalar->getValue(operation_string); - tile_defaults.operations.push_back(operation_ref.str()); - } - } - } - } else if (key_ref == "default_ports") { - auto *value_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (value_node) { - tile_defaults.default_ports.clear(); - for (auto &port_node : *value_node) { - auto *port_scalar = llvm::dyn_cast_or_null(&port_node); - if (port_scalar) { - llvm::SmallString<64> port_string; - llvm::StringRef port_ref = port_scalar->getValue(port_string); - tile_defaults.default_ports.push_back(port_ref.str()); - } - } - } - } - } - return true; -} -// Helper function to parse tile override coordinates and ID. -void parseTileOverrideCoordinates(llvm::yaml::MappingNode *overrideMap, mlir::neura::TileOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.id = static_cast(tempValue); - } - } - } else if (keyRef == "x") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.x = static_cast(tempValue); - } - } - } else if (keyRef == "y") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.y = static_cast(tempValue); - } - } + if (key_ref == kNumRegisters) { + int temp_value = 0; + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) + tile_defaults.num_registers = temp_value; + } else if (key_ref == kOperations) { + parseYamlStringSequence(key_value_pair.getValue(), tile_defaults.operations); + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown tile_defaults key: " << key_ref << "\n"; } } } // Helper function to parse tile override operations and registers. -void parseTileOverrideOperations(llvm::yaml::MappingNode *overrideMap, mlir::neura::TileOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "operations") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - override.operations.clear(); - for (auto &operationNode : *valueNode) { - auto *operationScalar = llvm::dyn_cast_or_null(&operationNode); - if (operationScalar) { - llvm::SmallString<64> operationString; - llvm::StringRef operationRef = operationScalar->getValue(operationString); - override.operations.push_back(operationRef.str()); - } - } - } - } else if (keyRef == "num_registers") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.num_registers = static_cast(tempValue); - } - } - } - } -} +void parseTileOverrideOperations(llvm::yaml::MappingNode *override_map, mlir::neura::TileOverride &override) { + for (auto &key_value_pair : *override_map) { + auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); + if (!key_node) continue; + llvm::SmallString<64> key_string; + llvm::StringRef key_ref = key_node->getValue(key_string); -// Helper function to parse tile override ports and memory. -void parseTileOverridePortsAndMemory(llvm::yaml::MappingNode *overrideMap, mlir::neura::TileOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "ports") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - override.ports.clear(); - for (auto &portNode : *valueNode) { - auto *portScalar = llvm::dyn_cast_or_null(&portNode); - if (portScalar) { - llvm::SmallString<64> portString; - llvm::StringRef portRef = portScalar->getValue(portString); - override.ports.push_back(portRef.str()); - } - } - } - } else if (keyRef == "memory") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - for (auto &memoryKeyValuePair : *valueNode) { - auto *memoryKeyNode = llvm::dyn_cast_or_null(memoryKeyValuePair.getKey()); - if (!memoryKeyNode) continue; - - llvm::SmallString<64> memoryKeyString; - llvm::StringRef memoryKeyRef = memoryKeyNode->getValue(memoryKeyString); - - if (memoryKeyRef == "capacity") { - auto *memoryValueNode = llvm::dyn_cast_or_null(memoryKeyValuePair.getValue()); - if (memoryValueNode) { - llvm::SmallString<64> memoryValueString; - llvm::StringRef memoryValueRef = memoryValueNode->getValue(memoryValueString); - long long tempValue = 0; - if (!memoryValueRef.getAsInteger(10, tempValue)) { - override.memory.capacity = static_cast(tempValue); - } - } - } - } - } + if (key_ref == kOperations) { + parseYamlStringSequence(key_value_pair.getValue(), override.operations); + } else if (key_ref == kNumRegisters) { + int temp_value = 0; + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) + override.num_registers = temp_value; + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown tile_override key: " << key_ref << "\n"; } } } // Helper function to parse a single tile override. -void parseSingleTileOverride(llvm::yaml::MappingNode *overrideMap, mlir::neura::TileOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.id = static_cast(tempValue); - } - } - } else if (keyRef == "x") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.x = static_cast(tempValue); - } - } - } else if (keyRef == "y") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.y = static_cast(tempValue); - } - } - } else if (keyRef == "operations") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - override.operations.clear(); - for (auto &operationNode : *valueNode) { - auto *operationScalar = llvm::dyn_cast_or_null(&operationNode); - if (operationScalar) { - llvm::SmallString<64> operationString; - llvm::StringRef operationRef = operationScalar->getValue(operationString); - override.operations.push_back(operationRef.str()); - } - } - } - } else if (keyRef == "num_registers") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.num_registers = static_cast(tempValue); - } - } - } else if (keyRef == "ports") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - override.ports.clear(); - for (auto &portNode : *valueNode) { - auto *portScalar = llvm::dyn_cast_or_null(&portNode); - if (portScalar) { - llvm::SmallString<64> portString; - llvm::StringRef portRef = portScalar->getValue(portString); - override.ports.push_back(portRef.str()); - } - } - } - } else if (keyRef == "memory") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - for (auto &memoryKeyValuePair : *valueNode) { - auto *memoryKeyNode = llvm::dyn_cast_or_null(memoryKeyValuePair.getKey()); - if (!memoryKeyNode) continue; - - llvm::SmallString<64> memoryKeyString; - llvm::StringRef memoryKeyRef = memoryKeyNode->getValue(memoryKeyString); - - if (memoryKeyRef == "capacity") { - auto *memoryValueNode = llvm::dyn_cast_or_null(memoryKeyValuePair.getValue()); - if (memoryValueNode) { - llvm::SmallString<64> memoryValueString; - llvm::StringRef memoryValueRef = memoryValueNode->getValue(memoryValueString); - long long tempValue = 0; - if (!memoryValueRef.getAsInteger(10, tempValue)) { - override.memory.capacity = static_cast(tempValue); - } - } - } - } - } +void parseSingleTileOverride(llvm::yaml::MappingNode *override_map, mlir::neura::TileOverride &override) { + for (auto &key_value_pair : *override_map) { + auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); + if (!key_node) continue; + llvm::SmallString<64> key_string; + llvm::StringRef key_ref = key_node->getValue(key_string); + + int temp_value = 0; + if (key_ref == kCgraX) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.cgra_x = temp_value; + } else if (key_ref == kCgraY) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.cgra_y = temp_value; + } else if (key_ref == kTileX) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.tile_x = temp_value; + } else if (key_ref == kTileY) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.tile_y = temp_value; + } else if (key_ref == kOperations) { + parseYamlStringSequence(key_value_pair.getValue(), override.operations); + } else if (key_ref == kNumRegisters) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.num_registers = temp_value; + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown tile_override key: " << key_ref << "\n"; } } } @@ -315,7 +146,6 @@ bool parseTileOverrides(llvm::yaml::SequenceNode *tile_overrides_seq, std::vecto for (auto &override_node : *tile_overrides_seq) { auto *override_map = llvm::dyn_cast_or_null(&override_node); if (!override_map) continue; - mlir::neura::TileOverride override; parseSingleTileOverride(override_map, override); tile_overrides.push_back(override); @@ -328,184 +158,49 @@ bool parseLinkDefaults(llvm::yaml::MappingNode *link_defaults_map, mlir::neura:: for (auto &key_value_pair : *link_defaults_map) { auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); if (!key_node) continue; - llvm::SmallString<64> key_string; llvm::StringRef key_ref = key_node->getValue(key_string); - - if (key_ref == "latency") { - auto *value_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (value_node) { - llvm::SmallString<64> value_string; - llvm::StringRef value_ref = value_node->getValue(value_string); - long long temp_value = 0; - if (!value_ref.getAsInteger(10, temp_value)) { - link_defaults.latency = static_cast(temp_value); - } - } - } else if (key_ref == "bandwidth") { - auto *value_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (value_node) { - llvm::SmallString<64> value_string; - llvm::StringRef value_ref = value_node->getValue(value_string); - long long temp_value = 0; - if (!value_ref.getAsInteger(10, temp_value)) { - link_defaults.bandwidth = static_cast(temp_value); - } - } - } - } - return true; -} - -// Helper function to parse link override properties. -void parseLinkOverrideProperties(llvm::yaml::MappingNode *overrideMap, mlir::neura::LinkOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.id = static_cast(tempValue); - } - } - } else if (keyRef == "latency") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.latency = static_cast(tempValue); - } - } - } else if (keyRef == "bandwidth") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.bandwidth = static_cast(tempValue); - } - } - } - } -} -// Helper function to parse link override tile IDs and existence. -void parseLinkOverrideTilesAndExistence(llvm::yaml::MappingNode *overrideMap, mlir::neura::LinkOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "src_tile_id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.src_tile_id = static_cast(tempValue); - } - } - } else if (keyRef == "dst_tile_id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.dst_tile_id = static_cast(tempValue); - } - } - } else if (keyRef == "existence") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - override.existence = (valueRef == "true" || valueRef == "True" || valueRef == "1"); - } + int temp_value = 0; + if (key_ref == kLatency) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) link_defaults.latency = temp_value; + } else if (key_ref == kBandwidth) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) link_defaults.bandwidth = temp_value; + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown link_defaults key: " << key_ref << "\n"; } } + return true; } // Helper function to parse a single link override. -void parseSingleLinkOverride(llvm::yaml::MappingNode *overrideMap, mlir::neura::LinkOverride &override) { - for (auto &keyValuePair : *overrideMap) { - auto *keyNode = llvm::dyn_cast_or_null(keyValuePair.getKey()); - if (!keyNode) continue; - - llvm::SmallString<64> keyString; - llvm::StringRef keyRef = keyNode->getValue(keyString); - - if (keyRef == "id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.id = static_cast(tempValue); - } - } - } else if (keyRef == "latency") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.latency = static_cast(tempValue); - } - } - } else if (keyRef == "bandwidth") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.bandwidth = static_cast(tempValue); - } - } - } else if (keyRef == "src_tile_id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.src_tile_id = static_cast(tempValue); - } - } - } else if (keyRef == "dst_tile_id") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - long long tempValue = 0; - if (!valueRef.getAsInteger(10, tempValue)) { - override.dst_tile_id = static_cast(tempValue); - } - } - } else if (keyRef == "existence") { - auto *valueNode = llvm::dyn_cast_or_null(keyValuePair.getValue()); - if (valueNode) { - llvm::SmallString<64> valueString; - llvm::StringRef valueRef = valueNode->getValue(valueString); - override.existence = (valueRef == "true" || valueRef == "True" || valueRef == "1"); +void parseSingleLinkOverride(llvm::yaml::MappingNode *override_map, mlir::neura::LinkOverride &override) { + for (auto &key_value_pair : *override_map) { + auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); + if (!key_node) continue; + llvm::SmallString<64> key_string; + llvm::StringRef key_ref = key_node->getValue(key_string); + + int temp_value = 0; + if (key_ref == kLatency) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.latency = temp_value; + } else if (key_ref == kBandwidth) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.bandwidth = temp_value; + } else if (key_ref == kSrcTileX) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.src_tile_x = temp_value; + } else if (key_ref == kSrcTileY) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.src_tile_y = temp_value; + } else if (key_ref == kDstTileX) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.dst_tile_x = temp_value; + } else if (key_ref == kDstTileY) { + if (parseYamlScalarInt(key_value_pair.getValue(), temp_value)) override.dst_tile_y = temp_value; + } else if (key_ref == kExistence) { + std::string value; + if (parseYamlScalarString(key_value_pair.getValue(), value)) { + override.existence = (value == "true" || value == "True" || value == "1"); } + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown link_override key: " << key_ref << "\n"; } } } @@ -515,7 +210,6 @@ bool parseLinkOverrides(llvm::yaml::SequenceNode *link_overrides_seq, std::vecto for (auto &override_node : *link_overrides_seq) { auto *override_map = llvm::dyn_cast_or_null(&override_node); if (!override_map) continue; - mlir::neura::LinkOverride override; parseSingleLinkOverride(override_map, override); link_overrides.push_back(override); @@ -525,11 +219,11 @@ bool parseLinkOverrides(llvm::yaml::SequenceNode *link_overrides_seq, std::vecto // Helper function to parse topology string to BaseTopology enum mlir::neura::BaseTopology parseTopologyString(const std::string& topology_str) { - if (topology_str == "mesh") { + if (topology_str == kMesh) { return mlir::neura::BaseTopology::MESH; - } else if (topology_str == "king_mesh" || topology_str == "king mesh") { + } else if (topology_str == kKingMesh || topology_str == kKingMeshAlt) { return mlir::neura::BaseTopology::KING_MESH; - } else if (topology_str == "ring") { + } else if (topology_str == kRing) { return mlir::neura::BaseTopology::RING; } else { // Default to mesh if unknown topology @@ -538,96 +232,93 @@ mlir::neura::BaseTopology parseTopologyString(const std::string& topology_str) { } // Helper function to parse architecture YAML configuration. -bool parseArchitectureYAML(llvm::yaml::Document &doc, int &width, int &height, int &max_ii, - mlir::neura::TileDefaults &tile_defaults, - std::vector &tile_overrides, - mlir::neura::LinkDefaults &link_defaults, - std::vector &link_overrides, - mlir::neura::BaseTopology &base_topology) { +bool parseArchitectureYaml(llvm::yaml::Document &doc, + int &multi_cgra_rows, + int &multi_cgra_columns, + mlir::neura::BaseTopology &multi_cgra_base_topology, + int &per_cgra_rows, + int &per_cgra_columns, + mlir::neura::BaseTopology &per_cgra_base_topology, + int &max_ctrl_mem_items, + mlir::neura::TileDefaults &tile_defaults, + std::vector &tile_overrides, + mlir::neura::LinkDefaults &link_defaults, + std::vector &link_overrides) { auto *root = doc.getRoot(); - if (!root) { - llvm::errs() << "[MapToAcceleratorPass] Empty YAML document\n"; - return false; - } - + if (!root) return yamlParseError("Empty YAML document"); auto *root_map = llvm::dyn_cast(root); - if (!root_map) { - llvm::errs() << "[MapToAcceleratorPass] YAML root is not a mapping\n"; - return false; - } + if (!root_map) return yamlParseError("YAML root is not a mapping"); - // Iterate root mapping ONCE; find 'architecture' and 'tile_defaults'. for (auto &key_value_pair : *root_map) { auto *key_node = llvm::dyn_cast_or_null(key_value_pair.getKey()); if (!key_node) continue; - llvm::SmallString<64> key_string; llvm::StringRef key_ref = key_node->getValue(key_string); - - if (key_ref == "architecture") { - auto *architecture_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (!architecture_map) continue; - - // Iterate architecture mapping ONCE; read width/height in the same pass. - for (auto &architecture_key_value_pair : *architecture_map) { - auto *architecture_key_node = llvm::dyn_cast_or_null(architecture_key_value_pair.getKey()); - if (!architecture_key_node) continue; - - llvm::SmallString<64> architecture_key_string; - llvm::StringRef architecture_key_ref = architecture_key_node->getValue(architecture_key_string); - if (architecture_key_ref == "width" || architecture_key_ref == "height" || architecture_key_ref == "max_allowed_ii_by_hw") { - auto *architecture_value_node = llvm::dyn_cast_or_null(architecture_key_value_pair.getValue()); - if (!architecture_value_node) continue; - - llvm::SmallString<64> architecture_value_string; - llvm::StringRef architecture_value_ref = architecture_value_node->getValue(architecture_value_string); - long long temp_value = 0; - if (!architecture_value_ref.getAsInteger(10, temp_value)) { - if (architecture_key_ref == "width") width = static_cast(temp_value); - if (architecture_key_ref == "height") height = static_cast(temp_value); - if (architecture_key_ref == "max_allowed_ii_by_hw") { - max_ii = static_cast(temp_value); - } - } - } else { - continue; - } - } - } else if (key_ref == "tile_defaults") { - auto *tile_defaults_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (tile_defaults_map) { - parseTileDefaults(tile_defaults_map, tile_defaults); - } - } else if (key_ref == "tile_overrides") { - auto *tile_overrides_seq = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (tile_overrides_seq) { - parseTileOverrides(tile_overrides_seq, tile_overrides); - } - } else if (key_ref == "link_defaults") { - auto *link_defaults_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (link_defaults_map) { - parseLinkDefaults(link_defaults_map, link_defaults); - } - } else if (key_ref == "link_overrides") { - auto *link_overrides_seq = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (link_overrides_seq) { - parseLinkOverrides(link_overrides_seq, link_overrides); - } - } else if (key_ref == "base_topology") { - auto *topology_node = llvm::dyn_cast_or_null(key_value_pair.getValue()); - if (topology_node) { - llvm::SmallString<64> topology_string; - llvm::StringRef topology_ref = topology_node->getValue(topology_string); - base_topology = parseTopologyString(topology_ref.str()); - } - } - } - if (width <= 0 || height <= 0) { - width = -1; - height = -1; + if (key_ref == kArchitecture) { + // Not used in this parser, but could be handled here. + continue; + } else if (key_ref == kMultiCgraDefaults) { + auto *multi_cgra_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (!multi_cgra_map) continue; + for (auto &multi_cgra_map_key_value_pair : *multi_cgra_map) { + auto *multi_cgra_map_key_node = llvm::dyn_cast_or_null(multi_cgra_map_key_value_pair.getKey()); + if (!multi_cgra_map_key_node) continue; + llvm::SmallString<64> multi_cgra_map_key_string; + llvm::StringRef multi_cgra_map_key_ref = multi_cgra_map_key_node->getValue(multi_cgra_map_key_string); + int temp_value = 0; + if (multi_cgra_map_key_ref == kRows) { + if (parseYamlScalarInt(multi_cgra_map_key_value_pair.getValue(), temp_value)) + multi_cgra_rows = temp_value; + } else if (multi_cgra_map_key_ref == kColumns) { + if (parseYamlScalarInt(multi_cgra_map_key_value_pair.getValue(), temp_value)) + multi_cgra_columns = temp_value; + } else if (multi_cgra_map_key_ref == kBaseTopology) { + std::string topo_str; + if (parseYamlScalarString(multi_cgra_map_key_value_pair.getValue(), topo_str)) + multi_cgra_base_topology = parseTopologyString(topo_str); + } + } + } else if (key_ref == kPerCgraDefaults) { + auto *per_cgra_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (!per_cgra_map) continue; + for (auto &per_cgra_map_key_value_pair : *per_cgra_map) { + auto *per_cgra_map_key_node = llvm::dyn_cast_or_null(per_cgra_map_key_value_pair.getKey()); + if (!per_cgra_map_key_node) continue; + llvm::SmallString<64> per_cgra_map_key_string; + llvm::StringRef per_cgra_map_key_ref = per_cgra_map_key_node->getValue(per_cgra_map_key_string); + int temp_value = 0; + if (per_cgra_map_key_ref == kRows) { + if (parseYamlScalarInt(per_cgra_map_key_value_pair.getValue(), temp_value)) + per_cgra_rows = temp_value; + } else if (per_cgra_map_key_ref == kColumns) { + if (parseYamlScalarInt(per_cgra_map_key_value_pair.getValue(), temp_value)) + per_cgra_columns = temp_value; + } else if (per_cgra_map_key_ref == kBaseTopology) { + std::string topo_str; + if (parseYamlScalarString(per_cgra_map_key_value_pair.getValue(), topo_str)) + per_cgra_base_topology = parseTopologyString(topo_str); + } else if (per_cgra_map_key_ref == kCtrlMemItems) { + if (parseYamlScalarInt(per_cgra_map_key_value_pair.getValue(), temp_value)) + max_ctrl_mem_items = temp_value; + } + } + } else if (key_ref == kTileDefaults) { + auto *tile_defaults_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (tile_defaults_map) parseTileDefaults(tile_defaults_map, tile_defaults); + } else if (key_ref == kTileOverrides) { + auto *tile_overrides_seq = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (tile_overrides_seq) parseTileOverrides(tile_overrides_seq, tile_overrides); + } else if (key_ref == kLinkDefaults) { + auto *link_defaults_map = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (link_defaults_map) parseLinkDefaults(link_defaults_map, link_defaults); + } else if (key_ref == kLinkOverrides) { + auto *link_overrides_seq = llvm::dyn_cast_or_null(key_value_pair.getValue()); + if (link_overrides_seq) parseLinkOverrides(link_overrides_seq, link_overrides); + } else { + llvm::errs() << "[MapToAcceleratorPass] Unknown YAML root key: " << key_ref << "\n"; + } } - return true; } @@ -670,27 +361,28 @@ struct MapToAcceleratorPass void runOnOperation() override { ModuleOp module = getOperation(); + llvm::errs() << "[MapToAcceleratorPass] Starting mapping pass...\n"; std::unique_ptr mapping_strategy; - StringRef mapping_strategy_stringRef(mappingStrategy.getValue()); + StringRef mapping_strategy_string_ref(mappingStrategy.getValue()); StringRef backtrack_config_stringRef(backtrackConfig.getValue()); - StringRef mapping_mode_stringRef(mappingMode.getValue()); - bool is_spatial_only = (mapping_mode_stringRef == "spatial-only"); - if (is_spatial_only || mapping_mode_stringRef == "spatial-temporal" || - mapping_mode_stringRef.empty()) { - if (mapping_mode_stringRef.empty()) { - mapping_mode_stringRef = "spatial-temporal"; + StringRef mapping_mode_string_ref(mappingMode.getValue()); + bool is_spatial_only = (mapping_mode_string_ref == "spatial-only"); + if (is_spatial_only || mapping_mode_string_ref == "spatial-temporal" || + mapping_mode_string_ref.empty()) { + if (mapping_mode_string_ref.empty()) { + mapping_mode_string_ref = "spatial-temporal"; } llvm::errs() << "[MapToAcceleratorPass] Using Mapping Mode: " - << mapping_mode_stringRef << "\n"; + << mapping_mode_string_ref << "\n"; } else { llvm::errs() << "[MapToAcceleratorPass] Unsupported mapping mode: " - << mapping_mode_stringRef << "\n"; + << mapping_mode_string_ref << "\n"; return; } - if (mapping_strategy_stringRef == "heuristic" || - mapping_strategy_stringRef.empty()) { - mapping_strategy_stringRef = "heuristic"; + if (mapping_strategy_string_ref == "heuristic" || + mapping_strategy_string_ref.empty()) { + mapping_strategy_string_ref = "heuristic"; if (backtrack_config_stringRef == "simple") { mapping_strategy = std::make_unique(1, 1); @@ -736,56 +428,77 @@ struct MapToAcceleratorPass } } else { llvm::errs() << "[MapToAcceleratorPass] Unsupported mapping strategy: " - << mapping_strategy_stringRef << "\n"; + << mapping_strategy_string_ref << "\n"; return; } // Handle architecture specification file + constexpr int kMultiCgraDefaultRows = 1; + constexpr int kMultiCgraDefaultColumns = 1; + constexpr int kPerCgraDefaultRows = 4; + constexpr int kPerCgraDefaultColumns = 4; + constexpr int kDefaultMaxCtrlMemItems = 20; + std::string architecture_spec_file = mlir::neura::getArchitectureSpecFile(); - int yaml_width = -1; - int yaml_height = -1; - int yaml_max_ii = 20; // Default max_ii = 20 - mlir::neura::TileDefaults yaml_tile_defaults; + int multi_cgra_rows = kMultiCgraDefaultRows; + int multi_cgra_columns = kMultiCgraDefaultColumns; + int per_cgra_rows = kPerCgraDefaultRows; + int per_cgra_columns = kPerCgraDefaultColumns; + int max_ctrl_mem_items = kDefaultMaxCtrlMemItems; + mlir::neura::TileDefaults tile_defaults; std::vector tile_overrides; - mlir::neura::LinkDefaults yaml_link_defaults; + mlir::neura::LinkDefaults link_defaults; std::vector link_overrides; - mlir::neura::BaseTopology base_topology = mlir::neura::BaseTopology::MESH; // Default to mesh + mlir::neura::BaseTopology multi_cgra_base_topology = mlir::neura::BaseTopology::MESH; + mlir::neura::BaseTopology per_cgra_base_topology = mlir::neura::BaseTopology::MESH; + if (!architecture_spec_file.empty()) { // Use LLVM YAML parser to validate the YAML syntax (no mapping yet) - llvm::ErrorOr> bufferOrErr = + llvm::ErrorOr> buffer_or_err = llvm::MemoryBuffer::getFile(architecture_spec_file); - if (!bufferOrErr) { + if (!buffer_or_err) { llvm::errs() << "[MapToAcceleratorPass] Failed to open architecture specification file: " << architecture_spec_file << "\n"; return; } llvm::SourceMgr sm; - sm.AddNewSourceBuffer(std::move(*bufferOrErr), llvm::SMLoc()); - llvm::yaml::Stream yamlStream(sm.getMemoryBuffer(sm.getMainFileID())->getBuffer(), sm); - - bool parseFailed = false; - llvm::yaml::Document &firstDoc = *yamlStream.begin(); - (void)firstDoc; // ensure document is created - if (yamlStream.failed()) { - parseFailed = true; + sm.AddNewSourceBuffer(std::move(*buffer_or_err), llvm::SMLoc()); + llvm::yaml::Stream yaml_stream(sm.getMemoryBuffer(sm.getMainFileID())->getBuffer(), sm); + + bool parse_failed = false; + llvm::yaml::Document &yaml_doc = *yaml_stream.begin(); + (void)yaml_doc; // ensure document is created + if (yaml_stream.failed()) { + parse_failed = true; } - if (parseFailed) { + if (parse_failed) { llvm::errs() << "[MapToAcceleratorPass] YAML parse error in: " << architecture_spec_file << "\n"; return; } // Parse YAML configuration - if (!parseArchitectureYAML(firstDoc, yaml_width, yaml_height, yaml_max_ii, yaml_tile_defaults, tile_overrides, yaml_link_defaults, link_overrides, base_topology)) { + if (!parseArchitectureYaml(yaml_doc, + multi_cgra_rows, + multi_cgra_columns, + multi_cgra_base_topology, + per_cgra_rows, + per_cgra_columns, + per_cgra_base_topology, + max_ctrl_mem_items, + tile_defaults, + tile_overrides, + link_defaults, + link_overrides)) { return; } - } else { + llvm::errs() << "[MapToAcceleratorPass] No architecture specification file provided.\n"; } - + // assert(false); module.walk([&](func::FuncOp func) { // Skips functions not targeting the neura accelerator. auto accel_attr = func->getAttrOfType("accelerator"); @@ -801,10 +514,10 @@ struct MapToAcceleratorPass // If steering mode, enforce spatial-only mapping. if (is_steering_mode) { - if (mapping_mode_stringRef != "spatial-only") { + if (mapping_mode_string_ref != "spatial-only") { func.emitError() << "Steering IR mode requires spatial-only mapping, " << "but got mapping mode: " - << mapping_mode_stringRef; + << mapping_mode_string_ref; signalPassFailure(); return; } @@ -841,17 +554,22 @@ struct MapToAcceleratorPass } else if (!longest) { rec_mii = 1; // No recurrence cycles found, set MII to 1. } - - // Construct architecture from YAML configuration - int arch_w = (yaml_width > 0 ? yaml_width : 4); - int arch_h = (yaml_height > 0 ? yaml_height : 4); // Always use full constructor with YAML configuration - Architecture architecture(arch_w, arch_h, yaml_tile_defaults, tile_overrides, yaml_link_defaults, link_overrides, base_topology); + Architecture architecture(multi_cgra_rows, + multi_cgra_columns, + multi_cgra_base_topology, + per_cgra_rows, + per_cgra_columns, + per_cgra_base_topology, + tile_defaults, + tile_overrides, + link_defaults, + link_overrides); int res_mii = calculateResMii(func, architecture); - const int possibleMinII = std::max(rec_mii, res_mii); - const int maxII = yaml_max_ii; // Use YAML config (default 20 if not specified) + const int possible_min_ii = std::max(rec_mii, res_mii); + const int max_ii = max_ctrl_mem_items; // Use YAML config (default 20 if not specified) std::vector topologically_sorted_ops = getTopologicallySortedOps(func); @@ -882,7 +600,7 @@ struct MapToAcceleratorPass << " (ALAP level: " << level << ")\n"; } // assert(false); - for (int ii = possibleMinII; ii <= maxII; ++ii) { + for (int ii = possible_min_ii; ii <= max_ii; ++ii) { llvm::errs() << "[MapToAcceleratorPass] Start mapping with target II of " << ii << "\n"; @@ -900,14 +618,14 @@ struct MapToAcceleratorPass ctx, {NamedAttribute(StringAttr::get(ctx, "x_tiles"), IntegerAttr::get(IntegerType::get(ctx, 32), - architecture.getWidth())), + architecture.getPerCgraColumns())), NamedAttribute(StringAttr::get(ctx, "y_tiles"), IntegerAttr::get(IntegerType::get(ctx, 32), - architecture.getHeight())), + architecture.getPerCgraRows())), NamedAttribute(StringAttr::get(ctx, "mapping_strategy"), - StringAttr::get(ctx, mapping_strategy_stringRef)), + StringAttr::get(ctx, mapping_strategy_string_ref)), NamedAttribute(StringAttr::get(ctx, "mapping_mode"), - StringAttr::get(ctx, mapping_mode_stringRef)), + StringAttr::get(ctx, mapping_mode_string_ref)), NamedAttribute(StringAttr::get(ctx, "compiled_ii"), IntegerAttr::get(IntegerType::get(ctx, 32), ii)), NamedAttribute( diff --git a/test/arch_spec/arch_spec_example.yaml b/test/arch_spec/arch_spec_example.yaml index 6b905e3a..82eac1eb 100644 --- a/test/arch_spec/arch_spec_example.yaml +++ b/test/arch_spec/arch_spec_example.yaml @@ -1,72 +1,78 @@ architecture: - name: "NeuraCGRA" + name: "NeuraMultiCgra" version: "1.0" - width: 4 - height: 4 - max_allowed_ii_by_hw: 20 + +multi_cgra_defaults: + base_topology: "mesh" + rows: 2 + columns: 2 + memory: + capacity: 2048 + +cgra_defaults: + rows: 4 + columns: 4 + ctrl_mem_items: 20 + base_topology: "mesh" + memory: + banks: 4 tile_defaults: num_registers: 128 - default_ports: ["N", "S", "W", "E"] operations: ["add", "mul", "sub", "div", "rem", "fadd", "fmul", "fsub", "fdiv", "or", "not", "icmp", "fcmp", "sel", "cast", "sext", "zext", "shl", "vfmul", "fadd_fadd", "fmul_fadd", "data_mov", "ctrl_mov", "reserve", "grant_predicate", "grant_once", "grant_always", "loop_control", "phi", "constant"] # comprehensive operation set link_defaults: latency: 1 bandwidth: 32 -base_topology: "mesh" - link_overrides: - - id: 1 + - src_cgra_x: 0 + src_cgra_y: 0 + dst_cgra_x: 0 + dst_cgra_y: 0 + src_tile_x: 0 + src_tile_y: 0 + dst_tile_x: 1 + dst_tile_y: 1 latency: 2 bandwidth: 32 - src_tile_id: 0 - dst_tile_id: 9 - existence: true - - - id: 2 - latency: 3 - bandwidth: 32 - src_tile_id: 0 - dst_tile_id: 8 existence: true - - latency: 3 + - src_cgra_x: 1 + src_cgra_y: 0 + dst_cgra_x: 1 + dst_cgra_y: 0 + src_tile_x: 1 + src_tile_y: 1 + dst_tile_x: 0 + dst_tile_y: 0 + latency: 2 bandwidth: 32 - src_tile_id: 0 - dst_tile_id: 1 existence: true tile_overrides: - - id: 0 - x: 0 - y: 0 + - cgra_x: 0 + cgra_y: 0 + tile_x: 0 + tile_y: 0 operations: ["load"] num_registers: 32 - ports: ["S", "E"] + existence: true - - id: 3 - x: 3 - y: 0 + - cgra_x: 1 + cgra_y: 0 + tile_x: 3 + tile_y: 0 operations: ["store"] num_registers: 32 - ports: ["W"] - - - id: 5 - x: 1 - y: 1 - operations: ["add", "mul"] - num_registers: 32 - memory: - capacity: 2048 - ports: ["N", "S", "E", "W"] # optional: matches defaults + existence: true - - id: 6 - x: 2 - y: 1 - operations: [] + - cgra_x: 1 + cgra_y: 0 + tile_x: 1 + tile_y: 1 num_registers: 32 - ports: ["E", "W"] + existence: false extensions: placeholder: false diff --git a/test/arch_spec/architecture.yaml b/test/arch_spec/architecture.yaml index 5d8ff80a..a998f131 100644 --- a/test/arch_spec/architecture.yaml +++ b/test/arch_spec/architecture.yaml @@ -1,21 +1,26 @@ architecture: - name: "NeuraCGRA" + name: "NeuraMultiCgra" version: "1.0" - width: 4 - height: 4 - max_allowed_ii_by_hw: 20 + +multi_cgra_defaults: + base_topology: "mesh" + rows: 1 + columns: 1 + +per_cgra_defaults: + rows: 4 + columns: 4 + ctrl_mem_items: 20 + base_topology: "mesh" tile_defaults: num_registers: 32 - default_ports: ["N", "S", "W", "E"] operations: ["add", "mul", "sub", "div", "rem", "fadd", "fmul", "fsub", "fdiv", "or", "not", "icmp", "fcmp", "sel", "cast", "sext", "zext", "shl", "vfmul", "fadd_fadd", "fmul_fadd", "data_mov", "ctrl_mov", "reserve", "grant_predicate", "grant_once", "grant_always", "loop_control", "phi", "constant", "load", "store", "return", "load_indexed", "store_indexed", "alloca"] link_defaults: latency: 1 bandwidth: 32 -base_topology: "mesh" - link_overrides: tile_overrides: diff --git a/test/code_gen/test_code_generate.mlir b/test/code_gen/test_code_generate.mlir index d1524f5e..d6264003 100644 --- a/test/code_gen/test_code_generate.mlir +++ b/test/code_gen/test_code_generate.mlir @@ -7,10 +7,12 @@ // RUN: --insert-data-mov \ // RUN: --map-to-accelerator="mapping-strategy=heuristic" \ // RUN: --architecture-spec=../arch_spec/architecture.yaml \ -// RUN: --generate-code -o %t-mapping.mlir -// RUN: FileCheck %s --input-file=%t-mapping.mlir -check-prefix=MAPPING -// RUN: FileCheck %s --input-file=tmp-generated-instructions.yaml --check-prefix=YAML -// RUN: FileCheck %s --input-file=tmp-generated-instructions.asm --check-prefix=ASM +// RUN: --generate-code + +// -o %t-mapping.mlir +// RN: FileCheck %s --input-file=%t-mapping.mlir -check-prefix=MAPPING +// RN: FileCheck %s --input-file=tmp-generated-instructions.yaml --check-prefix=YAML +// RN: FileCheck %s --input-file=tmp-generated-instructions.asm --check-prefix=ASM func.func @loop_test() -> f32 {