diff --git a/include/NeuraDialect/Architecture/Architecture.h b/include/NeuraDialect/Architecture/Architecture.h index dfd81237..35a52538 100644 --- a/include/NeuraDialect/Architecture/Architecture.h +++ b/include/NeuraDialect/Architecture/Architecture.h @@ -5,8 +5,8 @@ #include #include #include -#include #include +#include #include #include @@ -31,12 +31,7 @@ enum class FunctionUnitKind { }; // Enum for supported operation types. -enum OperationKind { - IAdd = 0, - IMul = 1, - FAdd = 2, - FMul = 3 -}; +enum OperationKind { IAdd = 0, IMul = 1, FAdd = 2, FMul = 3 }; //===----------------------------------------------------------------------===// // BasicResource: abstract base class for Tile, Link, etc. @@ -75,9 +70,9 @@ class FunctionUnit : public BasicResource { return res && res->getKind() == ResourceKind::FunctionUnit; } - Tile* getTile() const; + Tile *getTile() const; - void setTile(Tile* tile); + void setTile(Tile *tile); std::set getSupportedOperations() const { return supported_operations; @@ -97,7 +92,7 @@ class FunctionUnit : public BasicResource { private: int id; - Tile* tile; + Tile *tile; }; class FixedPointAdder : public FunctionUnit { @@ -148,11 +143,11 @@ class Tile : public BasicResource { int getX() const; int getY() const; - void linkDstTile(Link* link, Tile* tile); - const std::set& getDstTiles() const; - const std::set& getSrcTiles() const; - const std::set& getOutLinks() const; - const std::set& getInLinks() const; + void linkDstTile(Link *link, Tile *tile); + const std::set &getDstTiles() const; + const std::set &getSrcTiles() const; + const std::set &getOutLinks() const; + const std::set &getInLinks() const; void addFunctionUnit(std::unique_ptr func_unit) { assert(func_unit && "Cannot add null function unit"); @@ -167,12 +162,13 @@ class Tile : public BasicResource { return true; } } - // TODO: Check if the tile can support the operation based on its capabilities. + // TODO: Check if the tile can support the operation based on its + // capabilities. // @Jackcuii, https://github.com/coredac/dataflow/issues/82. return true; } - void addRegisterFileCluster(RegisterFileCluster* register_file_cluster); + void addRegisterFileCluster(RegisterFileCluster *register_file_cluster); const RegisterFileCluster *getRegisterFileCluster() const; @@ -183,12 +179,13 @@ class Tile : public BasicResource { private: int id; int x, y; - std::set src_tiles; - std::set dst_tiles; - std::set in_links; - std::set out_links; - std::vector> functional_unit_storage; // Owns FUs. - std::set functional_units; // Non-owning, for fast lookup. + std::set src_tiles; + std::set dst_tiles; + std::set in_links; + std::set out_links; + std::vector> + functional_unit_storage; // Owns FUs. + std::set functional_units; // Non-owning, for fast lookup. RegisterFileCluster *register_file_cluster = nullptr; }; @@ -209,15 +206,15 @@ class Link : public BasicResource { static bool classof(const BasicResource *res) { return res && res->getKind() == ResourceKind::Link; } - Tile* getSrcTile() const; - Tile* getDstTile() const; + Tile *getSrcTile() const; + Tile *getDstTile() const; - void connect(Tile* src, Tile* dst); + void connect(Tile *src, Tile *dst); private: int id; - Tile* src_tile; - Tile* dst_tile; + Tile *src_tile; + Tile *dst_tile; }; //===----------------------------------------------------------------------===// @@ -238,15 +235,15 @@ class Register : public BasicResource { return res && res->getKind() == ResourceKind::Register; } - Tile* getTile() const; + Tile *getTile() const; - void setRegisterFile(RegisterFile* register_file); + void setRegisterFile(RegisterFile *register_file); - RegisterFile* getRegisterFile() const; + RegisterFile *getRegisterFile() const; private: int id; - RegisterFile* register_file; + RegisterFile *register_file; }; //===----------------------------------------------------------------------===// @@ -267,19 +264,19 @@ class RegisterFile : public BasicResource { return res && res->getKind() == ResourceKind::RegisterFile; } - Tile* getTile() const; + Tile *getTile() const; - void setRegisterFileCluster(RegisterFileCluster* register_file_cluster); + void setRegisterFileCluster(RegisterFileCluster *register_file_cluster); - void addRegister(Register* reg); + void addRegister(Register *reg); - const std::map& getRegisters() const; - RegisterFileCluster* getRegisterFileCluster() const; + const std::map &getRegisters() const; + RegisterFileCluster *getRegisterFileCluster() const; private: int id; - std::map registers; - RegisterFileCluster* register_file_cluster = nullptr; + std::map registers; + RegisterFileCluster *register_file_cluster = nullptr; }; //===----------------------------------------------------------------------===// @@ -293,29 +290,32 @@ class RegisterFileCluster : public BasicResource { std::string getType() const override { return "register_file_cluster"; } - ResourceKind getKind() const override { return ResourceKind::RegisterFileCluster; } + ResourceKind getKind() const override { + return ResourceKind::RegisterFileCluster; + } static bool classof(const BasicResource *res) { return res && res->getKind() == ResourceKind::RegisterFileCluster; } - Tile* getTile() const; - void setTile(Tile* tile); + Tile *getTile() const; + void setTile(Tile *tile); - void addRegisterFile(RegisterFile* register_file); - const std::map& getRegisterFiles() const; + void addRegisterFile(RegisterFile *register_file); + const std::map &getRegisterFiles() const; private: int id; - Tile* tile; - std::map register_files; + Tile *tile; + std::map register_files; }; //===----------------------------------------------------------------------===// struct PairHash { std::size_t operator()(const std::pair &coord) const { - return std::hash()(coord.first) ^ (std::hash()(coord.second) << 1); + return std::hash()(coord.first) ^ + (std::hash()(coord.second) << 1); } }; @@ -325,22 +325,28 @@ class Architecture { public: Architecture(int width, int height); - Tile* getTile(int id); - Tile* getTile(int x, int y); + Tile *getTile(int id); + Tile *getTile(int x, int y); + + int getWidth() const { return width; } + int getHeight() const { return height; } - Link* getLink(int id); + Link *getLink(int id); int getNumTiles() const; - std::vector getAllTiles() const; - std::vector getAllLinks() const; + std::vector getAllTiles() const; + std::vector getAllLinks() const; private: // TODO: Model architecture in detail, e.g., ports, registers, crossbars, etc. // https://github.com/coredac/dataflow/issues/52. std::vector> tile_storage; std::vector> link_storage; - std::unordered_map id_to_tile; - std::unordered_map, Tile*, PairHash> coord_to_tile; + std::unordered_map id_to_tile; + std::unordered_map, Tile *, PairHash> coord_to_tile; + + int width; + int height; }; } // namespace neura diff --git a/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h b/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h index 9c233828..f6a6d5ff 100644 --- a/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h +++ b/include/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.h @@ -40,10 +40,18 @@ class HeuristicMapping : public Mapping { std::set &critical_ops, const Architecture &architecture, MappingState &mapping_state); + // Gets the sorted candidate locations for a given operation based on spatial + // execution model. + std::vector + calculateSpatialAward(Operation *op, std::set &critical_ops, + int target_level, const Architecture &architecture, + const MappingState &mapping_state); + // Configuration parameters. - int max_location_to_try; // Maximum number of locations to try for - // each op - int max_backtrack_depth; // Maximum depth for backtracking + // Maximum number of locations to try for each op. + int max_location_to_try; + // Maximum depth for backtracking. + int max_backtrack_depth; }; } // namespace neura } // namespace mlir diff --git a/include/NeuraDialect/Mapping/Mapping.h b/include/NeuraDialect/Mapping/Mapping.h index 16b9148c..2054965c 100644 --- a/include/NeuraDialect/Mapping/Mapping.h +++ b/include/NeuraDialect/Mapping/Mapping.h @@ -21,6 +21,8 @@ class Mapping { // Gets the name of this strategy virtual std::string getName() const = 0; + +private: }; } // namespace neura diff --git a/include/NeuraDialect/Mapping/MappingState.h b/include/NeuraDialect/Mapping/MappingState.h index 1ec75ab8..b3e152ad 100644 --- a/include/NeuraDialect/Mapping/MappingState.h +++ b/include/NeuraDialect/Mapping/MappingState.h @@ -55,7 +55,7 @@ namespace neura { // Tracks placement and routing of ops on the CGRA. class MappingState { public: - MappingState(const Architecture &arch, int II); + MappingState(const Architecture &arch, int II, bool is_spatial_only); // Binds a (tile/link, time_step) location to an operation. bool bindOp(const MappingLoc &loc, Operation *op); @@ -138,6 +138,7 @@ class MappingState { private: // Initiation interval. int II; + bool is_spatial_only; static constexpr int kMaxSteps = 10; std::set occupied_locs; diff --git a/include/NeuraDialect/Mapping/mapping_util.h b/include/NeuraDialect/Mapping/mapping_util.h index 87442c5a..21af298a 100644 --- a/include/NeuraDialect/Mapping/mapping_util.h +++ b/include/NeuraDialect/Mapping/mapping_util.h @@ -1,16 +1,24 @@ #pragma once -#include "mlir/IR/Operation.h" #include "NeuraDialect/Architecture/Architecture.h" #include "NeuraDialect/Mapping/MappingState.h" +#include "mlir/IR/Operation.h" namespace mlir { namespace neura { +// Returns the kind of operation from the MLIR operation. +OperationKind getOperationKindFromMlirOp(Operation *op); -// Represents a recurrence cycle rooted at a reserve operation and closed by ctrl_mov. +// Returns true if the operation does not need CGRA tile placement. +bool is_non_materialized(Operation *op); + +// Represents a recurrence cycle rooted at a reserve operation and closed by +// ctrl_mov. struct RecurrenceCycle { - SmallVector operations; // Ordered list of operations in the cycle. - int length = 0; // Number of operations excluding reserve/ctrl_mov. + // Ordered list of operations in the cycle. + SmallVector operations; + // Number of operations excluding reserve/ctrl_mov. + int length = 0; }; // Collects recurrence cycles rooted at reserve and closed by ctrl_mov. @@ -26,20 +34,19 @@ std::vector getTopologicallySortedOps(Operation *func_op); // contains a vector of operations at the same ALAP (as late as possible) // level and the level number. std::vector> - getOpsInAlapLevels(const std::vector &sorted_ops, - const std::set &critical_ops); +getOpsInAlapLevels(const std::vector &sorted_ops, + const std::set &critical_ops); // Flattens the level buckets into a vector of pairs (operation, level). -std::vector> - flatten_level_buckets(const std::vector> &level_buckets); +std::vector> flatten_level_buckets( + const std::vector> &level_buckets); -// Gets the physical hops from the producers to the tile, which is used for estimating -// the award of a location for placement. -int getPhysicalHops(const std::vector &producers, - Tile *tile, +// Gets the physical hops from the producers to the tile, which is used for +// estimating the award of a location for placement. +int getPhysicalHops(const std::vector &producers, Tile *tile, const MappingState &mapping_state); -Operation* getMaterializedProducer(Value operand); +Operation *getMaterializedProducer(Value operand); // Collects the real users of an operation, excluding ctrl_mov and data_mov. llvm::SmallVector getMaterializedUserOps(Operation *op); @@ -49,60 +56,50 @@ llvm::SmallVector getMaterializedUserOps(Operation *op); Operation *getMaterializedBackwardUser(Operation *op); // Attempts to route a data move operation from src_loc to dst_loc. -bool tryRouteDataMove(Operation *mov, - MappingLoc src_loc, - MappingLoc dst_loc, - bool is_backward_move, - const MappingState &mapping_state, +bool tryRouteDataMove(Operation *mov, MappingLoc src_loc, MappingLoc dst_loc, + bool is_backward_move, const MappingState &mapping_state, std::vector &path_out); -bool tryRouteForwardMove(Operation *mov_op, - MappingLoc src_loc, - MappingLoc dst_loc, - const MappingState &state, +bool tryRouteForwardMove(Operation *mov_op, MappingLoc src_loc, + MappingLoc dst_loc, const MappingState &state, std::vector &path_out); -bool tryRouteBackwardMove(Operation *mov_op, - MappingLoc src_loc, - MappingLoc dst_loc, - const MappingState &state, - std::vector &path_out); +bool tryRouteBackwardMove(Operation *mov_op, MappingLoc src_loc, + MappingLoc dst_loc, const MappingState &state, + std::vector &path_out); -// Gets the ctrl_mov users of an operation, empty vector is returned if no ctrl_mov users found. +// Gets the ctrl_mov users of an operation, empty vector is returned if no +// ctrl_mov users found. llvm::SmallVector getCtrlMovUsers(Operation *op); -// Maps a materialized operation to the accelerator, and routes the dataflow from -// the producers to the given op. -bool placeAndRoute(Operation *op, const MappingLoc &target_loc, MappingState &mapping_state); +// Maps a materialized operation to the accelerator, and routes the dataflow +// from the producers to the given op. +bool placeAndRoute(Operation *op, const MappingLoc &target_loc, + MappingState &mapping_state); -// Calculates the award of mapping locations for a given op, the returned locations -// are sorted based on the award. +// Calculates the award of mapping locations for a given op, the returned +// locations are sorted based on the award. std::vector calculateAward(Operation *op, std::set &critical_ops, int target_level, const Architecture &architecture, const MappingState &mapping_state); -void updateAward(std::map &locs_with_award, - MappingLoc loc, int award); +void updateAward(std::map &locs_with_award, MappingLoc loc, + int award); -bool canReachLocInTime(const MappingLoc &src_loc, - const MappingLoc &dst_loc, - int deadline_step, - const MappingState &mapping_state); +bool canReachLocInTime(const MappingLoc &src_loc, const MappingLoc &dst_loc, + int deadline_step, const MappingState &mapping_state); bool canReachLocInTime(const std::vector &producers, - const MappingLoc &target_loc, - int deadline_step, + const MappingLoc &target_loc, int deadline_step, const MappingState &mapping_state); // Gets an available register (for the given time range) in the given tile. // The end_time is exclusive, meaning the register should be available // until end_time - 1. Returns nullptr if no available register found. -Register *getAvailableRegister(const MappingState &mapping_state, - Tile *tile, - int start_time, - int exclusive_end_time); +Register *getAvailableRegister(const MappingState &mapping_state, Tile *tile, + int start_time, int exclusive_end_time); } // namespace neura } // namespace mlir diff --git a/lib/NeuraDialect/Architecture/Architecture.cpp b/lib/NeuraDialect/Architecture/Architecture.cpp index 0c08d9a8..933cc209 100644 --- a/lib/NeuraDialect/Architecture/Architecture.cpp +++ b/lib/NeuraDialect/Architecture/Architecture.cpp @@ -42,7 +42,7 @@ const std::set &Tile::getOutLinks() const { return out_links; } const std::set &Tile::getInLinks() const { return in_links; } -void Tile::addRegisterFileCluster(RegisterFileCluster* register_file_cluster) { +void Tile::addRegisterFileCluster(RegisterFileCluster *register_file_cluster) { assert(register_file_cluster && "Cannot add null register file cluster"); if (this->register_file_cluster != nullptr) { llvm::errs() << "Warning: Overwriting existing register file cluster (" @@ -55,13 +55,14 @@ void Tile::addRegisterFileCluster(RegisterFileCluster* register_file_cluster) { register_file_cluster->setTile(this); } -const RegisterFileCluster* Tile::getRegisterFileCluster() const { +const RegisterFileCluster *Tile::getRegisterFileCluster() const { return register_file_cluster; } const std::vector Tile::getRegisterFiles() const { - std::vector all_register_files; - for (const auto& [id, file] : this->register_file_cluster->getRegisterFiles()) { + std::vector all_register_files; + for (const auto &[id, file] : + this->register_file_cluster->getRegisterFiles()) { all_register_files.push_back(file); } return all_register_files; @@ -69,8 +70,9 @@ const std::vector Tile::getRegisterFiles() const { const std::vector Tile::getRegisters() const { std::vector all_registers; - for (const auto& [reg_file_id, reg_file] : this->register_file_cluster->getRegisterFiles()) { - for (const auto& [reg_id, reg] : reg_file->getRegisters()) { + for (const auto &[reg_file_id, reg_file] : + this->register_file_cluster->getRegisterFiles()) { + for (const auto &[reg_id, reg] : reg_file->getRegisters()) { all_registers.push_back(reg); } } @@ -104,13 +106,9 @@ FunctionUnit::FunctionUnit(int id) { this->id = id; } int FunctionUnit::getId() const { return id; } -void FunctionUnit::setTile(Tile* tile) { - this->tile = tile; -} +void FunctionUnit::setTile(Tile *tile) { this->tile = tile; } -Tile *FunctionUnit::getTile() const { - return this->tile; -} +Tile *FunctionUnit::getTile() const { return this->tile; } //===----------------------------------------------------------------------===// // Register @@ -124,13 +122,11 @@ Tile *Register::getTile() const { return this->register_file ? register_file->getTile() : nullptr; } -void Register::setRegisterFile(RegisterFile* register_file) { +void Register::setRegisterFile(RegisterFile *register_file) { this->register_file = register_file; } -RegisterFile *Register::getRegisterFile() const { - return this->register_file; -} +RegisterFile *Register::getRegisterFile() const { return this->register_file; } //===----------------------------------------------------------------------===// // Register File @@ -141,23 +137,25 @@ RegisterFile::RegisterFile(int id) { this->id = id; } int RegisterFile::getId() const { return id; } Tile *RegisterFile::getTile() const { - return this->register_file_cluster ? register_file_cluster->getTile() : nullptr; + return this->register_file_cluster ? register_file_cluster->getTile() + : nullptr; } -void RegisterFile::setRegisterFileCluster(RegisterFileCluster* register_file_cluster) { +void RegisterFile::setRegisterFileCluster( + RegisterFileCluster *register_file_cluster) { this->register_file_cluster = register_file_cluster; } -void RegisterFile::addRegister(Register* reg) { +void RegisterFile::addRegister(Register *reg) { registers[reg->getId()] = reg; reg->setRegisterFile(this); } -const std::map& RegisterFile::getRegisters() const { +const std::map &RegisterFile::getRegisters() const { return this->registers; } -RegisterFileCluster* RegisterFile::getRegisterFileCluster() const { +RegisterFileCluster *RegisterFile::getRegisterFileCluster() const { return this->register_file_cluster; } @@ -169,20 +167,17 @@ RegisterFileCluster::RegisterFileCluster(int id) { this->id = id; } int RegisterFileCluster::getId() const { return id; } -void RegisterFileCluster::setTile(Tile* tile) { - this->tile = tile; -} +void RegisterFileCluster::setTile(Tile *tile) { this->tile = tile; } -Tile *RegisterFileCluster::getTile() const { - return this->tile; -} +Tile *RegisterFileCluster::getTile() const { return this->tile; } -void RegisterFileCluster::addRegisterFile(RegisterFile* register_file) { +void RegisterFileCluster::addRegisterFile(RegisterFile *register_file) { register_files[register_file->getId()] = register_file; register_file->setRegisterFileCluster(this); } -const std::map& RegisterFileCluster::getRegisterFiles() const { +const std::map & +RegisterFileCluster::getRegisterFiles() const { return this->register_files; } @@ -191,6 +186,8 @@ const std::map& RegisterFileCluster::getRegisterFiles() cons //===----------------------------------------------------------------------===// Architecture::Architecture(int width, int height) { + this->width = width; + this->height = height; const int num_tiles = width * height; // Initializes tiles. @@ -230,15 +227,16 @@ Architecture::Architecture(int width, int height) { register_file_1->addRegister(register_3); // Assembles register files into a cluster. - RegisterFileCluster *register_file_cluster = new RegisterFileCluster(y * width + x); + RegisterFileCluster *register_file_cluster = + new RegisterFileCluster(y * width + x); register_file_cluster->addRegisterFile(register_file_0); register_file_cluster->addRegisterFile(register_file_1); // Adds register file cluster to the tile. tile->addRegisterFileCluster(register_file_cluster); llvm::errs() << "Tile (" << x << ", " << y - << ") added register file cluster with ID: " - << register_file_cluster->getId() << "\n"; + << ") added register file cluster with ID: " + << register_file_cluster->getId() << "\n"; } } diff --git a/lib/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.cpp b/lib/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.cpp index d7777938..113a55f2 100644 --- a/lib/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.cpp +++ b/lib/NeuraDialect/Mapping/HeuristicMapping/HeuristicMapping.cpp @@ -6,18 +6,11 @@ namespace mlir { namespace neura { - -// Returns true if the operation does not need CGRA tile placement. -inline bool is_non_materialized(Operation *op) { - // Returns true if the operation does not need CGRA tile placement. - return mlir::isa(op); -} - bool HeuristicMapping::map( std::vector> &sorted_ops_with_levels, std::set &critical_ops, const Architecture &architecture, MappingState &mapping_state) { - // Start the backtracking mapping process from the first operation. + // Starts the backtracking mapping process. return mapWithBacktrack(sorted_ops_with_levels, critical_ops, architecture, mapping_state); } @@ -86,9 +79,10 @@ bool HeuristicMapping::mapWithBacktrack( } Operation *current_op = materialized_ops[current_op_index].first; - std::vector candidate_locs = calculateAward( - current_op, critical_ops, materialized_ops[current_op_index].second, - architecture, mapping_state); + std::vector candidate_locs; + candidate_locs = calculateAward(current_op, critical_ops, + materialized_ops[current_op_index].second, + architecture, mapping_state); if (candidate_locs.empty()) { llvm::outs() << "[HeuristicMapping] No candidate locations found " diff --git a/lib/NeuraDialect/Mapping/Mapping.cpp b/lib/NeuraDialect/Mapping/Mapping.cpp index 7e8c4004..d9328e9d 100644 --- a/lib/NeuraDialect/Mapping/Mapping.cpp +++ b/lib/NeuraDialect/Mapping/Mapping.cpp @@ -1,2 +1,5 @@ #include "NeuraDialect/Mapping/Mapping.h" -#include \ No newline at end of file +#include + +// TODO: Move common functions from mapping_util.cpp to Mapping.cpp +// Issue Link: https://github.com/coredac/dataflow/issues/107 \ No newline at end of file diff --git a/lib/NeuraDialect/Mapping/MappingState.cpp b/lib/NeuraDialect/Mapping/MappingState.cpp index d918602e..4177fa27 100644 --- a/lib/NeuraDialect/Mapping/MappingState.cpp +++ b/lib/NeuraDialect/Mapping/MappingState.cpp @@ -5,7 +5,9 @@ using namespace mlir; using namespace mlir::neura; -MappingState::MappingState(const Architecture &arch, int II) : II(II) {} +MappingState::MappingState(const Architecture &arch, int II, + bool is_spatial_only) + : II(II), is_spatial_only(is_spatial_only) {} bool MappingState::bindOp(const MappingLoc &loc, Operation *op) { loc_to_op[loc] = op; @@ -31,14 +33,26 @@ void MappingState::unbindOp(Operation *op) { } bool MappingState::isAvailableAcrossTime(const MappingLoc &loc) const { - // Checks the availability across time domain. - for (int t = loc.time_step % II; t < II * kMaxSteps; t += II) { - MappingLoc check_loc = {loc.resource, t}; - if (occupied_locs.find(check_loc) != occupied_locs.end()) { - return false; + // For spatial mapping, checks if the location is available across all time. + if (this->is_spatial_only) { + for (int t = 0; t < II * kMaxSteps; ++t) { + MappingLoc check_loc = {loc.resource, t}; + if (occupied_locs.find(check_loc) != occupied_locs.end()) { + return false; + } } + return true; + } else { + + // Checks the availability across time domain. + for (int t = loc.time_step % II; t < II * kMaxSteps; t += II) { + MappingLoc check_loc = {loc.resource, t}; + if (occupied_locs.find(check_loc) != occupied_locs.end()) { + return false; + } + } + return true; } - return true; } bool MappingState::isAvailableAcrossTimeInRange(BasicResource *resource, diff --git a/lib/NeuraDialect/Mapping/mapping_util.cpp b/lib/NeuraDialect/Mapping/mapping_util.cpp index c65aebe5..0a0ea45a 100644 --- a/lib/NeuraDialect/Mapping/mapping_util.cpp +++ b/lib/NeuraDialect/Mapping/mapping_util.cpp @@ -13,9 +13,9 @@ using namespace mlir; using namespace mlir::neura; -namespace { - -inline OperationKind getOperationKindFromMlirOp(Operation *op) { +namespace mlir { +namespace neura { +OperationKind getOperationKindFromMlirOp(Operation *op) { if (isa(op)) return IAdd; if (isa(op)) @@ -30,11 +30,15 @@ inline OperationKind getOperationKindFromMlirOp(Operation *op) { } // Returns true if the operation does not need CGRA tile placement. -inline bool is_non_materialized(Operation *op) { +bool is_non_materialized(Operation *op) { // Returns true if the operation does not need CGRA tile placement. return mlir::isa(op); } +} // namespace neura +} // namespace mlir + +namespace { // Traverses (backward) the operation graph starting from the given operation // towards reserve_value. void traverseAlongPath(Operation *op, Value reserve_value, diff --git a/lib/NeuraDialect/Transforms/FuseControlFlowPass.cpp b/lib/NeuraDialect/Transforms/FuseControlFlowPass.cpp index 7b6bc996..0eddf127 100644 --- a/lib/NeuraDialect/Transforms/FuseControlFlowPass.cpp +++ b/lib/NeuraDialect/Transforms/FuseControlFlowPass.cpp @@ -385,7 +385,7 @@ LogicalResult replaceWithLoopController(LoopInfo *loop_info, rewriter.create(loc, index_type, end_val, nullptr); Value step_val = loop_info->step_val; - rewriter.setInsertionPointAfter(end_val.getDefiningOp()); + rewriter.setInsertionPointAfter(step_val.getDefiningOp()); step_val = rewriter.create(loc, index_type, step_val, nullptr); diff --git a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp index ed4416b6..43762599 100644 --- a/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp +++ b/lib/NeuraDialect/Transforms/MapToAcceleratorPass.cpp @@ -10,6 +10,7 @@ #include "NeuraDialect/NeuraPasses.h" #include "NeuraDialect/NeuraTypes.h" #include "mlir/Dialect/Func/IR/FuncOps.h" +#include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Pass/Pass.h" #include "mlir/Transforms/GreedyPatternRewriteDriver.h" @@ -23,7 +24,6 @@ using namespace mlir::neura; #include "NeuraDialect/NeuraPasses.h.inc" namespace { - struct MapToAcceleratorPass : public PassWrapper> { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(MapToAcceleratorPass) @@ -45,6 +45,12 @@ struct MapToAcceleratorPass llvm::cl::desc("Mapping strategy to use for mapping operations to the " "accelerator. Options: heuristic (default)."), llvm::cl::init("heuristic")}; + Option mappingMode{ + *this, "mapping-mode", + llvm::cl::desc( + "Mapping mode to use for mapping operations to the " + "accelerator. Options: spatial-only, spatial-temporal (default)."), + llvm::cl::init("spatial-temporal")}; Option backtrackConfig{ *this, "backtrack-config", llvm::cl::desc( @@ -52,15 +58,31 @@ struct MapToAcceleratorPass "accelerator. Options: simple, greedy, exhaustive, " "customized=max_loc,max_depth (default " "max_loc=5, max_depth=3)"), - llvm::cl::init("heuristic")}; + llvm::cl::init("customized")}; void runOnOperation() override { ModuleOp module = getOperation(); std::unique_ptr mapping_strategy; StringRef mappingStrategy_stringRef(mappingStrategy.getValue()); StringRef backtrackConfig_stringRef(backtrackConfig.getValue()); + StringRef mappingMode_stringRef(mappingMode.getValue()); + bool is_spatial_only = (mappingMode_stringRef == "spatial-only"); + if (is_spatial_only || mappingMode_stringRef == "spatial-temporal" || + mappingMode_stringRef.empty()) { + if (mappingMode_stringRef.empty()) { + mappingMode_stringRef = "spatial-temporal"; + } + llvm::errs() << "[MapToAcceleratorPass] Using Mapping Mode: " + << mappingMode_stringRef << "\n"; + } else { + llvm::errs() << "[MapToAcceleratorPass] Unsupported mapping mode: " + << mappingMode_stringRef << "\n"; + return; + } + if (mappingStrategy_stringRef == "heuristic" || mappingStrategy_stringRef.empty()) { + mappingStrategy_stringRef = "heuristic"; if (backtrackConfig_stringRef == "simple") { mapping_strategy = std::make_unique(1, 1); @@ -145,16 +167,16 @@ struct MapToAcceleratorPass } else if (!longest) { rec_mii = 1; // No recurrence cycles found, set MII to 1. } - IntegerAttr rec_mii_attr = - IntegerAttr::get(IntegerType::get(func.getContext(), 32), rec_mii); - func->setAttr("RecMII", rec_mii_attr); + // IntegerAttr rec_mii_attr = + // IntegerAttr::get(IntegerType::get(func.getContext(), 32), rec_mii); + // func->setAttr("RecMII", rec_mii_attr); // AcceleratorConfig config{/*numTiles=*/8}; // Example Architecture architecture(4, 4); int res_mii = calculateResMii(func, architecture); - IntegerAttr res_mii_attr = - IntegerAttr::get(IntegerType::get(func.getContext(), 32), res_mii); - func->setAttr("ResMII", res_mii_attr); + // IntegerAttr res_mii_attr = + // IntegerAttr::get(IntegerType::get(func.getContext(), 32), res_mii); + // func->setAttr("ResMII", res_mii_attr); const int possibleMinII = std::max(rec_mii, res_mii); constexpr int maxII = 10; @@ -192,7 +214,7 @@ struct MapToAcceleratorPass << "[MapToAcceleratorPass] Start mapping with target II of " << ii << "\n"; // Creates a mapping state for the current II. - MappingState mapping_state(architecture, ii); + MappingState mapping_state(architecture, ii, is_spatial_only); if (mapping_strategy->map(sorted_ops_with_alap_levels, critical_ops, architecture, mapping_state)) { // success @@ -200,9 +222,31 @@ struct MapToAcceleratorPass << func.getName() << "' with II = " << ii << "\n"; mapping_state.dumpOpToLocs(); // logs to stderr mapping_state.encodeMappingState(); - func->setAttr( - "CompiledII", - IntegerAttr::get(IntegerType::get(func.getContext(), 32), ii)); + + // Sets the mapping_info attribute on the function. + auto ctx = func.getContext(); + DictionaryAttr mapping_info = DictionaryAttr::get( + ctx, + {NamedAttribute(StringAttr::get(ctx, "x_tiles"), + IntegerAttr::get(IntegerType::get(ctx, 32), + architecture.getWidth())), + NamedAttribute(StringAttr::get(ctx, "y_tiles"), + IntegerAttr::get(IntegerType::get(ctx, 32), + architecture.getHeight())), + NamedAttribute(StringAttr::get(ctx, "mapping_strategy"), + StringAttr::get(ctx, mappingStrategy_stringRef)), + NamedAttribute(StringAttr::get(ctx, "mapping_mode"), + StringAttr::get(ctx, mappingMode_stringRef)), + NamedAttribute(StringAttr::get(ctx, "compiled_ii"), + IntegerAttr::get(IntegerType::get(ctx, 32), ii)), + NamedAttribute( + StringAttr::get(ctx, "rec_mii"), + IntegerAttr::get(IntegerType::get(ctx, 32), rec_mii)), + NamedAttribute( + StringAttr::get(ctx, "res_mii"), + IntegerAttr::get(IntegerType::get(ctx, 32), res_mii))}); + + func->setAttr("mapping_info", mapping_info); break; } llvm::errs() << "[DEBUG] mapping failed for II = " << ii << "\n"; diff --git a/test/controflow_fuse/simple_loop/simple_loop.mlir b/test/controflow_fuse/simple_loop/simple_loop.mlir index a1851f43..4752c2f1 100644 --- a/test/controflow_fuse/simple_loop/simple_loop.mlir +++ b/test/controflow_fuse/simple_loop/simple_loop.mlir @@ -183,7 +183,7 @@ module attributes {} { // FUSE-NEXT: "neura.return"() : () -> () // FUSE-NEXT: } -// FUSE-MAPPING: func.func @_Z11simple_loopPiS_(%arg0: memref, %arg1: memref) attributes {CompiledII = 5 : i32, RecMII = 1 : i32, ResMII = 2 : i32, accelerator = "neura", llvm.linkage = #llvm.linkage} { +// FUSE-MAPPING: func.func @_Z11simple_loopPiS_(%arg0: memref, %arg1: memref) attributes {accelerator = "neura", llvm.linkage = #llvm.linkage, mapping_info = {compiled_ii = 5 : i32, mapping_mode = "spatial-temporal", mapping_strategy = "heuristic", rec_mii = 1 : i32, res_mii = 2 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { // FUSE-MAPPING-NEXT: %0 = "neura.grant_once"() <{constant_value = "%arg0"}> {mapping_locs = [{id = 11 : i32, resource = "tile", time_step = 1 : i32, x = 3 : i32, y = 2 : i32}]} : () -> !neura.data, i1> // FUSE-MAPPING-NEXT: %1 = "neura.grant_once"() <{constant_value = "%arg1"}> {mapping_locs = [{id = 11 : i32, resource = "tile", time_step = 4 : i32, x = 3 : i32, y = 2 : i32}]} : () -> !neura.data, i1> // FUSE-MAPPING-NEXT: %2 = "neura.grant_always"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 11 : i32, resource = "tile", time_step = 0 : i32, x = 3 : i32, y = 2 : i32}]} : () -> !neura.data diff --git a/test/controflow_fuse/simple_loop_reduction/simple_loop_reduction.mlir b/test/controflow_fuse/simple_loop_reduction/simple_loop_reduction.mlir index 679f5497..8b4044f6 100644 --- a/test/controflow_fuse/simple_loop_reduction/simple_loop_reduction.mlir +++ b/test/controflow_fuse/simple_loop_reduction/simple_loop_reduction.mlir @@ -161,7 +161,7 @@ module attributes {} { // FUSE-NEXT: } -// FUSE-MAPPING: func.func @_Z10simpleloopv() -> i32 attributes {CompiledII = 3 : i32, RecMII = 3 : i32, ResMII = 1 : i32, accelerator = "neura", llvm.linkage = #llvm.linkage} { +// FUSE-MAPPING: func.func @_Z10simpleloopv() -> i32 attributes {accelerator = "neura", llvm.linkage = #llvm.linkage, mapping_info = {compiled_ii = 3 : i32, mapping_mode = "spatial-temporal", mapping_strategy = "heuristic", rec_mii = 3 : i32, res_mii = 1 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { // FUSE-MAPPING-NEXT: %0 = "neura.grant_always"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 4 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 1 : i32}]} : () -> !neura.data // FUSE-MAPPING-NEXT: %1 = "neura.grant_always"() <{constant_value = 128 : i64}> {mapping_locs = [{id = 12 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 3 : i32}]} : () -> !neura.data // FUSE-MAPPING-NEXT: %2 = "neura.grant_once"() <{constant_value = 0 : i32}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 1 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data diff --git a/test/mapping_quality/branch_for.mlir b/test/mapping_quality/branch_for.mlir index 670e7459..4817c572 100644 --- a/test/mapping_quality/branch_for.mlir +++ b/test/mapping_quality/branch_for.mlir @@ -244,7 +244,7 @@ func.func @loop_test() -> f32 { // MOV-NEXT: "neura.return"(%49) : (!neura.data) -> () // MOV-NEXT: } -// MAPPING: func.func @loop_test() -> f32 attributes {CompiledII = 6 : i32, RecMII = 4 : i32, ResMII = 2 : i32, accelerator = "neura"} { +// MAPPING: func.func @loop_test() -> f32 attributes {accelerator = "neura", mapping_info = {compiled_ii = 6 : i32, mapping_mode = "spatial-temporal", mapping_strategy = "heuristic", rec_mii = 4 : i32, res_mii = 2 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { // MAPPING-NEXT: %0 = "neura.grant_once"() <{constant_value = 10 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 1 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data // MAPPING-NEXT: %1 = "neura.grant_once"() <{constant_value = 0 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data // MAPPING-NEXT: %2 = "neura.grant_once"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 2 : i32, resource = "tile", time_step = 0 : i32, x = 2 : i32, y = 0 : i32}]} : () -> !neura.data diff --git a/test/mapping_quality/tiny_loop.mlir b/test/mapping_quality/tiny_loop.mlir new file mode 100644 index 00000000..87aae182 --- /dev/null +++ b/test/mapping_quality/tiny_loop.mlir @@ -0,0 +1,134 @@ +// RUN: mlir-opt %s --lower-affine --convert-scf-to-cf --convert-cf-to-llvm -o %t-llvm.mlir +// RUN: mlir-neura-opt %t-llvm.mlir \ +// RUN: --assign-accelerator \ +// RUN: --lower-arith-to-neura \ +// RUN: --lower-memref-to-neura \ +// RUN: --lower-builtin-to-neura \ +// RUN: --lower-llvm-to-neura \ +// RUN: --canonicalize-cast \ +// RUN: --canonicalize-live-in \ +// RUN: | FileCheck %s + +// RUN: mlir-neura-opt %t-llvm.mlir \ +// RUN: --assign-accelerator \ +// RUN: --lower-arith-to-neura \ +// RUN: --lower-memref-to-neura \ +// RUN: --lower-builtin-to-neura \ +// RUN: --lower-llvm-to-neura \ +// RUN: --canonicalize-cast \ +// RUN: --canonicalize-live-in \ +// RUN: --leverage-predicated-value \ +// RUN: --transform-ctrl-to-data-flow \ +// RUN: --fuse-control-flow \ +// RUN: --fold-constant \ +// RUN: --insert-data-mov \ +// RUN: --map-to-accelerator="mapping-strategy=heuristic mapping-mode=spatial-only backtrack-config=customized=4,3" \ +// RUN: | FileCheck %s -check-prefix=SPATIAL + +// RUN: mlir-neura-opt %t-llvm.mlir \ +// RUN: --assign-accelerator \ +// RUN: --lower-arith-to-neura \ +// RUN: --lower-memref-to-neura \ +// RUN: --lower-builtin-to-neura \ +// RUN: --lower-llvm-to-neura \ +// RUN: --canonicalize-cast \ +// RUN: --canonicalize-live-in \ +// RUN: --leverage-predicated-value \ +// RUN: --transform-ctrl-to-data-flow \ +// RUN: --fuse-control-flow \ +// RUN: --fold-constant \ +// RUN: --insert-data-mov \ +// RUN: --map-to-accelerator="mapping-strategy=heuristic mapping-mode=spatial-temporal backtrack-config=customized=3,4" \ +// RUN: | FileCheck %s -check-prefix=SPATIAL-TEMPORAL + +module { + func.func @simple_add_loop() -> i64 { + %c0 = arith.constant 0 : index + %c10 = arith.constant 1 : i64 + %c1 = arith.constant 1 : index + %c16 = arith.constant 16 : index + + %result = scf.for %i = %c0 to %c16 step %c1 iter_args(%acc = %c10) -> (i64) { + %sum = arith.addi %acc, %acc : i64 + scf.yield %sum : i64 + } + return %result : i64 + } +} + +// CHECK: func.func @simple_add_loop() -> i64 attributes {accelerator = "neura"} { +// CHECK-NEXT: %0 = "neura.constant"() <{predicate = true, value = 16 : i64}> : () -> i64 +// CHECK-NEXT: %1 = "neura.constant"() <{predicate = true, value = 1 : i64}> : () -> i64 +// CHECK-NEXT: %2 = "neura.constant"() <{predicate = true, value = 1 : i64}> : () -> i64 +// CHECK-NEXT: %3 = "neura.constant"() <{predicate = true, value = 0 : i64}> : () -> i64 +// CHECK-NEXT: neura.br %3, %2, %0 : i64, i64, i64 to ^bb1 +// CHECK-NEXT: ^bb1(%4: i64, %5: i64, %6: i64): // 2 preds: ^bb0, ^bb2 +// CHECK-NEXT: %7 = "neura.icmp"(%4, %6) <{cmpType = "slt"}> : (i64, i64) -> i1 +// CHECK-NEXT: neura.cond_br %7 : i1 then %5, %4, %1, %0 : i64, i64, i64, i64 to ^bb2 else %5 : i64 to ^bb3 +// CHECK-NEXT: ^bb2(%8: i64, %9: i64, %10: i64, %11: i64): // pred: ^bb1 +// CHECK-NEXT: %12 = "neura.add"(%8, %8) : (i64, i64) -> i64 +// CHECK-NEXT: %13 = "neura.add"(%9, %10) : (i64, i64) -> i64 +// CHECK-NEXT: neura.br %13, %12, %11 : i64, i64, i64 to ^bb1 +// CHECK-NEXT: ^bb3(%14: i64): // pred: ^bb1 +// CHECK-NEXT: "neura.return"(%14) : (i64) -> () +// CHECK-NEXT: } + +// SPATIAL: func.func @simple_add_loop() -> i64 attributes {accelerator = "neura", mapping_info = {compiled_ii = 7 : i32, mapping_mode = "spatial-only", mapping_strategy = "heuristic", rec_mii = 3 : i32, res_mii = 1 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { +// SPATIAL-NEXT: %0 = "neura.grant_always"() <{constant_value = 16 : i64}> {mapping_locs = [{id = 2 : i32, resource = "tile", time_step = 0 : i32, x = 2 : i32, y = 0 : i32}]} : () -> !neura.data +// SPATIAL-NEXT: %1 = "neura.grant_always"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data +// SPATIAL-NEXT: %2 = "neura.grant_once"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 1 : i32, resource = "tile", time_step = 1 : i32, x = 1 : i32, y = 0 : i32}]} : () -> !neura.data +// SPATIAL-NEXT: %3 = "neura.grant_once"() <{constant_value = 0 : i64}> {mapping_locs = [{id = 11 : i32, resource = "tile", time_step = 0 : i32, x = 3 : i32, y = 2 : i32}]} : () -> !neura.data +// SPATIAL-NEXT: %4 = "neura.grant_always"() <{constant_value = true}> {mapping_locs = [{id = 10 : i32, resource = "tile", time_step = 0 : i32, x = 2 : i32, y = 2 : i32}]} : () -> !neura.data +// SPATIAL-NEXT: %5 = "neura.data_mov"(%4) {mapping_locs = [{id = 33 : i32, resource = "link", time_step = 0 : i32}, {id = 24 : i32, resource = "register", time_step = 1 : i32}, {id = 24 : i32, resource = "register", time_step = 2 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %6 = "neura.data_mov"(%3) {mapping_locs = [{id = 36 : i32, resource = "link", time_step = 0 : i32}, {id = 21 : i32, resource = "link", time_step = 1 : i32}, {id = 25 : i32, resource = "register", time_step = 2 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %7 = "neura.data_mov"(%0) {mapping_locs = [{id = 7 : i32, resource = "link", time_step = 0 : i32}, {id = 26 : i32, resource = "register", time_step = 1 : i32}, {id = 26 : i32, resource = "register", time_step = 2 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %8 = "neura.data_mov"(%1) {mapping_locs = [{id = 0 : i32, resource = "link", time_step = 0 : i32}, {id = 4 : i32, resource = "link", time_step = 1 : i32}, {id = 14 : i32, resource = "link", time_step = 2 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %nextindex, %valid = neura.loop_control(parent_valid = %5, start = %6, end = %7, step = %8) {iterationType = "increment", mapping_locs = [{id = 6 : i32, resource = "tile", time_step = 3 : i32, x = 2 : i32, y = 1 : i32}]} : !neura.data, !neura.data, !neura.data, !neura.data -> !neura.data, !neura.data +// SPATIAL-NEXT: %9 = "neura.data_mov"(%valid) {mapping_locs = [{id = 18 : i32, resource = "link", time_step = 3 : i32}, {id = 22 : i32, resource = "link", time_step = 4 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %10 = "neura.not"(%9) {mapping_locs = [{id = 3 : i32, resource = "tile", time_step = 5 : i32, x = 3 : i32, y = 0 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %11 = neura.reserve : !neura.data +// SPATIAL-NEXT: %12 = "neura.data_mov"(%2) {mapping_locs = [{id = 2 : i32, resource = "link", time_step = 1 : i32}, {id = 1 : i32, resource = "link", time_step = 2 : i32}, {id = 10 : i32, resource = "link", time_step = 3 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %13 = "neura.phi"(%11, %12) {mapping_locs = [{id = 5 : i32, resource = "tile", time_step = 4 : i32, x = 1 : i32, y = 1 : i32}]} : (!neura.data, !neura.data) -> !neura.data +// SPATIAL-NEXT: %14 = "neura.data_mov"(%13) {mapping_locs = [{id = 16 : i32, resource = "link", time_step = 4 : i32}, {id = 36 : i32, resource = "register", time_step = 5 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %15 = "neura.data_mov"(%valid) {mapping_locs = [{id = 20 : i32, resource = "link", time_step = 3 : i32}, {id = 31 : i32, resource = "link", time_step = 4 : i32}, {id = 37 : i32, resource = "register", time_step = 5 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %16 = neura.grant_predicate %14, %15 {mapping_locs = [{id = 9 : i32, resource = "tile", time_step = 6 : i32, x = 1 : i32, y = 2 : i32}]} : !neura.data, !neura.data -> !neura.data +// SPATIAL-NEXT: %17 = "neura.data_mov"(%13) {mapping_locs = [{id = 13 : i32, resource = "link", time_step = 4 : i32}, {id = 12 : i32, resource = "link", time_step = 5 : i32}, {id = 24 : i32, resource = "link", time_step = 6 : i32}, {id = 28 : i32, resource = "link", time_step = 7 : i32}, {id = 34 : i32, resource = "link", time_step = 8 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %18 = "neura.data_mov"(%10) {mapping_locs = [{id = 9 : i32, resource = "link", time_step = 5 : i32}, {id = 23 : i32, resource = "link", time_step = 6 : i32}, {id = 37 : i32, resource = "link", time_step = 7 : i32}, {id = 46 : i32, resource = "link", time_step = 8 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %19 = neura.grant_predicate %17, %18 {mapping_locs = [{id = 14 : i32, resource = "tile", time_step = 9 : i32, x = 2 : i32, y = 3 : i32}]} : !neura.data, !neura.data -> !neura.data +// SPATIAL-NEXT: %20 = "neura.data_mov"(%16) {mapping_locs = [{id = 30 : i32, resource = "link", time_step = 6 : i32}, {id = 52 : i32, resource = "register", time_step = 7 : i32}, {id = 52 : i32, resource = "register", time_step = 8 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %21 = "neura.data_mov"(%16) {mapping_locs = [{id = 27 : i32, resource = "link", time_step = 6 : i32}, {id = 26 : i32, resource = "link", time_step = 7 : i32}, {id = 38 : i32, resource = "link", time_step = 8 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: %22 = "neura.add"(%20, %21) {mapping_locs = [{id = 13 : i32, resource = "tile", time_step = 9 : i32, x = 1 : i32, y = 3 : i32}]} : (!neura.data, !neura.data) -> !neura.data +// SPATIAL-NEXT: neura.ctrl_mov %22 -> %11 {mapping_locs = [{id = 42 : i32, resource = "link", time_step = 9 : i32}, {id = 29 : i32, resource = "link", time_step = 10 : i32}]} : !neura.data !neura.data +// SPATIAL-NEXT: %23 = "neura.data_mov"(%19) {mapping_locs = [{id = 44 : i32, resource = "link", time_step = 9 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-NEXT: "neura.return"(%23) {mapping_locs = [{id = 15 : i32, resource = "tile", time_step = 10 : i32, x = 3 : i32, y = 3 : i32}]} : (!neura.data) -> () +// SPATIAL-NEXT: } + +// SPATIAL-TEMPORAL: func.func @simple_add_loop() -> i64 attributes {accelerator = "neura", mapping_info = {compiled_ii = 3 : i32, mapping_mode = "spatial-temporal", mapping_strategy = "heuristic", rec_mii = 3 : i32, res_mii = 1 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { +// SPATIAL-TEMPORAL-NEXT: %0 = "neura.grant_always"() <{constant_value = 16 : i64}> {mapping_locs = [{id = 4 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 1 : i32}]} : () -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %1 = "neura.grant_always"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 12 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 3 : i32}]} : () -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %2 = "neura.grant_once"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 1 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %3 = "neura.grant_once"() <{constant_value = 0 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %4 = "neura.grant_always"() <{constant_value = true}> {mapping_locs = [{id = 9 : i32, resource = "tile", time_step = 0 : i32, x = 1 : i32, y = 2 : i32}]} : () -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %5 = "neura.data_mov"(%4) {mapping_locs = [{id = 27 : i32, resource = "link", time_step = 0 : i32}, {id = 32 : i32, resource = "register", time_step = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %6 = "neura.data_mov"(%3) {mapping_locs = [{id = 1 : i32, resource = "link", time_step = 0 : i32}, {id = 12 : i32, resource = "link", time_step = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %7 = "neura.data_mov"(%0) {mapping_locs = [{id = 12 : i32, resource = "link", time_step = 0 : i32}, {id = 33 : i32, resource = "register", time_step = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %8 = "neura.data_mov"(%1) {mapping_locs = [{id = 39 : i32, resource = "link", time_step = 0 : i32}, {id = 34 : i32, resource = "register", time_step = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %nextindex, %valid = neura.loop_control(parent_valid = %5, start = %6, end = %7, step = %8) {iterationType = "increment", mapping_locs = [{id = 8 : i32, resource = "tile", time_step = 2 : i32, x = 0 : i32, y = 2 : i32}]} : !neura.data, !neura.data, !neura.data, !neura.data -> !neura.data, !neura.data +// SPATIAL-TEMPORAL-NEXT: %9 = "neura.data_mov"(%valid) {mapping_locs = [{id = 25 : i32, resource = "link", time_step = 2 : i32}, {id = 16 : i32, resource = "register", time_step = 3 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %10 = "neura.not"(%9) {mapping_locs = [{id = 4 : i32, resource = "tile", time_step = 4 : i32, x = 0 : i32, y = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %11 = neura.reserve : !neura.data +// SPATIAL-TEMPORAL-NEXT: %12 = "neura.data_mov"(%2) {mapping_locs = [{id = 1 : i32, resource = "link", time_step = 1 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %13 = "neura.phi"(%11, %12) {mapping_locs = [{id = 4 : i32, resource = "tile", time_step = 2 : i32, x = 0 : i32, y = 1 : i32}]} : (!neura.data, !neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %14 = "neura.data_mov"(%13) {mapping_locs = [{id = 12 : i32, resource = "link", time_step = 2 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %15 = "neura.data_mov"(%valid) {mapping_locs = []} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %16 = neura.grant_predicate %14, %15 {mapping_locs = [{id = 8 : i32, resource = "tile", time_step = 3 : i32, x = 0 : i32, y = 2 : i32}]} : !neura.data, !neura.data -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %17 = "neura.data_mov"(%13) {mapping_locs = [{id = 11 : i32, resource = "link", time_step = 2 : i32}, {id = 0 : i32, resource = "register", time_step = 3 : i32}, {id = 0 : i32, resource = "register", time_step = 4 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %18 = "neura.data_mov"(%10) {mapping_locs = [{id = 11 : i32, resource = "link", time_step = 4 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %19 = neura.grant_predicate %17, %18 {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 5 : i32, x = 0 : i32, y = 0 : i32}]} : !neura.data, !neura.data -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %20 = "neura.data_mov"(%16) {mapping_locs = []} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %21 = "neura.data_mov"(%16) {mapping_locs = []} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: %22 = "neura.add"(%20, %21) {mapping_locs = [{id = 8 : i32, resource = "tile", time_step = 4 : i32, x = 0 : i32, y = 2 : i32}]} : (!neura.data, !neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: neura.ctrl_mov %22 -> %11 {mapping_locs = [{id = 25 : i32, resource = "link", time_step = 4 : i32}]} : !neura.data !neura.data +// SPATIAL-TEMPORAL-NEXT: %23 = "neura.data_mov"(%19) {mapping_locs = [{id = 0 : i32, resource = "link", time_step = 5 : i32}]} : (!neura.data) -> !neura.data +// SPATIAL-TEMPORAL-NEXT: "neura.return"(%23) {mapping_locs = [{id = 1 : i32, resource = "tile", time_step = 6 : i32, x = 1 : i32, y = 0 : i32}]} : (!neura.data) -> () +// SPATIAL-TEMPORAL-NEXT: } \ No newline at end of file diff --git a/test/neura/ctrl/branch_for.mlir b/test/neura/ctrl/branch_for.mlir index c35211e6..b7196a5a 100644 --- a/test/neura/ctrl/branch_for.mlir +++ b/test/neura/ctrl/branch_for.mlir @@ -244,7 +244,7 @@ func.func @loop_test() -> f32 { // MOV-NEXT: "neura.return"(%49) : (!neura.data) -> () // MOV-NEXT: } -// MAPPING: func.func @loop_test() -> f32 attributes {CompiledII = 6 : i32, RecMII = 4 : i32, ResMII = 2 : i32, accelerator = "neura"} { +// MAPPING: func.func @loop_test() -> f32 attributes {accelerator = "neura", mapping_info = {compiled_ii = 6 : i32, mapping_mode = "spatial-temporal", mapping_strategy = "heuristic", rec_mii = 4 : i32, res_mii = 2 : i32, x_tiles = 4 : i32, y_tiles = 4 : i32}} { // MAPPING-NEXT: %0 = "neura.grant_once"() <{constant_value = 10 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 1 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data // MAPPING-NEXT: %1 = "neura.grant_once"() <{constant_value = 0 : i64}> {mapping_locs = [{id = 0 : i32, resource = "tile", time_step = 0 : i32, x = 0 : i32, y = 0 : i32}]} : () -> !neura.data // MAPPING-NEXT: %2 = "neura.grant_once"() <{constant_value = 1 : i64}> {mapping_locs = [{id = 2 : i32, resource = "tile", time_step = 0 : i32, x = 2 : i32, y = 0 : i32}]} : () -> !neura.data