Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the incremental mapping function, which re-utilizes the previous mapping results to acceleterate ccurrent mapping. #24

Merged
merged 13 commits into from
Sep 16, 2024
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Execution
- [optLatency](https://github.com/tancheng/CGRA-Mapper/blob/589fd61434966e4d4a44220b59854b1795bc7cde/test/param.json#L19): used to support multi-cycle execution. If this field is not specified, every operation is done in one single-cycle. Note that there is currently no hardware support for this feature, which is supposed to be used for performance exploration only.
- [optPipelined](https://github.com/tancheng/CGRA-Mapper/blob/589fd61434966e4d4a44220b59854b1795bc7cde/test/param.json#L23): used to enable pipelined execution of the multi-cycle operation (i.e., indicated in [optLatency](https://github.com/tancheng/CGRA-Mapper/blob/589fd61434966e4d4a44220b59854b1795bc7cde/test/param.json#L19)).
- [additionalFunc](https://github.com/tancheng/CGRA-Mapper/blob/589fd61434966e4d4a44220b59854b1795bc7cde/test/param.json#L24): used to enable specific functionalities on target tiles. Normally, we don't need to set this field as all the tiles already include most functionalities. By default, the `ld`/`st` is only enabled on the left most tiles. So if you wanna enable the memory access on the other tiles, this field needs to be provided.
- [incrementalMapping](https://github.com/yyan7223/CGRA-Mapper/blob/10aa217e9e995b6dfa4242e0ce121b79668e9995/test/param.json#L28C1-L28C33) `true` indicates incremental mapping while `false` indicates heuristic/exhaustive mapping. Incremental mapping re-utilizes the previous mapping results to accelerate current mapping.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering why we need to let the user perform the two-step experiment. Why cannot just set this to true, and it will automatically perform heuristic/exhaustive first, then, based on the generated .json and perform the incremental mapping?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine a situation that we firstly map the KERNEL1 with 200 DFGNodes on 400 CGRANodes, and the heuristic mapper takes 1 hour to finish this.

Then let's say KERNEL2 takes 10 of 400 CGRANodes from KERNEL1, normally we need to re-map KERNEL1 on the rest of 390 CGRANodes from the scratch, which will cost us 1 hour again. This is the time when we need the incremental mapping, we can simply set the incrementalMapping to true, then the mapping can finish within several minutes.

But for small DFG mapping on small CGRAs, the heuristic mapper has already been fast enough and we seem do not need incremental mapping to further accelerate the mapping, so that's why I set incrementalMapping default to false.

(I have not really tested the incremental mapping on large DFG and large CGRA, It will definitely bring significant mapping acceleration, but may require additional tricks to ensure mapping quality. Anyway, I think incremental mapping might be an interesting idea in CGRA just like it in FPGA)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. Does it mean:

  • We need to manually disable 10 nodes (before the second time mapping for KERNEL1) as those nodes are occupied by KERNEL2?
    • It is possible that the 10 nodes totally destroy the routing opportunities for the second time KERNEL1's mapping? So we have to re-map? How is this case handled?
  • IncrementalMapping needs to check whether the increMapInput.json exists in the folder?
    • If it exists, how to guarantee it is for KERNEL1, instead of some random kernels?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I don't think we need to manually do this. There should be some sort of task scheduler that is responsible for automatically generating resource allocation decisions and corresponding param.json for Kernel1 adn Kernel2, just like the DRIPS controller.
  • Yes it is possible, but we can add a mechanism in the future like if resource changes over 50% of CGRANodes, incremental mapping is automatically disabled and start to re-map, just like in Vivado.
  • Yes, IncrementalMapping should check whether increMapInput.json is corresponding to Kernel1, which can be achieved by comparing some fields in .json like KernelID. Or if developers use CGRA-Flow, we can simply add a message box and let them choose the correct .json.

Current merge request is just a initial version of incremental mapping, and I know there are lots of functions are incomplete, but I’m happy to complement all the related functions in the future and hope they actually contributes to the CGRA development rather than just some academic ideas.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But for now, if I want to use this feature, I need manually disable some tiles (before invoking the incremental mapping) to see its effect, right?

Can you please provide the description about the constraint (users need to guarantee that increMapInput.json exists and the incrementalMapping can only work on the same kernel (and users need to manually disable some tiles?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the updated README.md


- Run:
```
Expand Down
4 changes: 4 additions & 0 deletions src/CGRANode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,3 +579,7 @@ void CGRANode::disableAllFUs() {
m_supportComplex = false;
m_supportVectorization = false;
}

bool CGRANode::isDisabled() {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So now, disabled implicitly indicates two cases:

  • HW choice to disable it, no data can pass it, no operation can map on it, or even serve as a dead point in the fabric.
  • Another simultaneous kernel is occupying this CGRA tile/node, which makes it impossible for current kernel to leverage it.

Correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the confirmation, plz summarize above two cases and put the summary as comment above the m_disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think about it again, if CGRANode5 is allocated to Kernel1, m_disabled should be set to false in Kernel1's paramCGRA.json but true in other kernels' paramCGRA.json

return m_disabled;
}
1 change: 1 addition & 0 deletions src/CGRANode.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ class CGRANode {
void allocateReg(int, int, int, int);
int* getRegsAllocation(int);
void disable();
bool isDisabled();
void disableAllFUs();
};

Expand Down
223 changes: 213 additions & 10 deletions src/Mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ void Mapper::showSchedule(CGRA* t_cgra, DFG* t_dfg, int t_II,

if (cycle < t_II and t_parameterizableCGRA) {
for (int i=0; i<t_cgra->getLinkCount(); ++i) {
CGRALink* link = t_cgra->links[i];
CGRALink* link = t_cgra->links[i];
if (link->isOccupied(cycle, t_II, t_isStaticElasticCGRA)) {
string strSrcNodeID = to_string(link->getSrc()->getID());
string strDstNodeID = to_string(link->getDst()->getID());
Expand All @@ -528,7 +528,7 @@ void Mapper::showSchedule(CGRA* t_cgra, DFG* t_dfg, int t_II,
jsonLinks[strSrcNodeID][strDstNodeID] = jsonLinkDstCycles;
}
jsonLinks[strSrcNodeID][strDstNodeID].push_back(cycle);
}
}
}
}

Expand Down Expand Up @@ -563,15 +563,15 @@ void Mapper::showSchedule(CGRA* t_cgra, DFG* t_dfg, int t_II,
str_fu = "[ " + to_string(dfgNode->getID()) + " ]";
else
str_fu = "[ " + to_string(dfgNode->getID()) + " ]";
string strNodeID = to_string(t_cgra->nodes[i][j]->getID());
if (t_parameterizableCGRA) {
if (jsonTiles.find(strNodeID) == jsonTiles.end()) {
string strNodeID = to_string(t_cgra->nodes[i][j]->getID());
if (t_parameterizableCGRA) {
if (jsonTiles.find(strNodeID) == jsonTiles.end()) {
map<string, vector<int>> jsonTileCycleOps;
jsonTiles[strNodeID] = jsonTileCycleOps;
}
vector<int> jsonCycleOp { dfgNode->getID() };
jsonTiles[strNodeID][to_string(cycle % t_II)] = jsonCycleOp;
}
jsonTiles[strNodeID] = jsonTileCycleOps;
}
vector<int> jsonCycleOp { dfgNode->getID() };
jsonTiles[strNodeID][to_string(cycle % t_II)] = jsonCycleOp;
}
} else {
str_fu = "[ ]";
}
Expand Down Expand Up @@ -1346,3 +1346,206 @@ map<int, CGRANode*>* Mapper::getReorderPath(map<CGRANode*, int>* t_path) {
return reorderPath;
}

// Saves the mapping results to json file for subsequent incremental mapping
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Period at the end, thanks! Same to the others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry what do you mean?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mapping -> mapping. Sorry for being picky.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has fixed all similar issues

void Mapper::generateJSON4IncrementalMap(CGRA* t_cgra, DFG* t_dfg){
ofstream jsonFile("increMapInput.json", ios::out);
jsonFile<<"{"<<endl;
jsonFile<<" \"Opt2TileXY\":{"<<endl;
int idx = 0;
for (DFGNode* dfgNode: t_dfg->nodes) {
// Writes dfgnodeID, mapped CGRANode X and Y coordinates
jsonFile<<" \""<<dfgNode->getID()<<"\": {"<<endl; // opt id
jsonFile<<" \"x\":"<<m_mapping[dfgNode]->getX()<<","<<endl; // opt mapped tile x coordinate
jsonFile<<" \"y\":"<<m_mapping[dfgNode]->getY()<<endl; // opt mapped tile y coordinate
idx += 1;
if (idx < t_dfg->nodes.size()) jsonFile<<" },"<<endl;
else jsonFile<<" }"<<endl;
}
jsonFile<<" },"<<endl;

jsonFile<<" \"Tile2Level\":{"<<endl;
// Generates level informations of current mapping results
map<int, vector<CGRANode*>> FanIO_CGRANodes;
vector<int> FanIOs;
int numTiles = 0;
for (int i=0; i<t_cgra->getRows(); ++i) {
for (int j=0; j<t_cgra->getColumns(); ++j) {

// Records the number of FanIO for each tile.
CGRANode* currentCGRANode = t_cgra->nodes[i][j];
if (currentCGRANode->getInLinks() == 0) continue; // Only records tiles that have DFGNodes mapped
int FanIO = max(currentCGRANode->getInLinks()->size(), currentCGRANode->getOutLinks()->size());
FanIO_CGRANodes[FanIO].push_back(currentCGRANode);

// Records FanIO in the list if it appears for the first time
if (find(FanIOs.begin(), FanIOs.end(), FanIO) == FanIOs.end()) {
FanIOs.push_back(FanIO);
}

numTiles++;
}
}
std::sort(FanIOs.rbegin(), FanIOs.rend()); // Sorts FanIOs from big to small
idx = 0;
for (int level = 0; level < FanIOs.size(); level++) {
int FanIO = FanIOs[level];
vector<CGRANode*> tiles = FanIO_CGRANodes[FanIO];
for (auto tile : tiles) {
idx += 1;
if (idx < numTiles) jsonFile<<" \""<<tile->getID()<<"\":"<<level<<","<<endl;
else jsonFile<<" \""<<tile->getID()<<"\":"<<level<<endl;
}
}
jsonFile<<" }"<<endl;

jsonFile<<"}"<<endl;
}

// Reads from the referenced mapping results json file and generates variables for incremental mapping
int Mapper::readRefMapRes(CGRA* t_cgra, DFG* t_dfg){
ifstream refFile("./increMapInput.json");
if (!refFile.good()) {
cout<<"Incremental mapping requires increMapInput.json in current directory!"<<endl;
return -1;
}
json refs;
refFile >> refs;
CGRANodeID2Level.clear();
for (list<DFGNode*>::iterator dfgNode=t_dfg->nodes.begin(); dfgNode != t_dfg->nodes.end(); ++dfgNode) {
int dfgNodeID = (*dfgNode)->getID();
int x = refs["Opt2TileXY"][to_string(dfgNodeID)]["x"];
int y = refs["Opt2TileXY"][to_string(dfgNodeID)]["y"];
refMapRes[*dfgNode] = t_cgra->nodes[y][x];
int cgraNodeID = t_cgra->nodes[y][x]->getID();
CGRANodeID2Level[cgraNodeID] = refs["Tile2Level"][to_string(cgraNodeID)];
}

return 0;
}

// Generates variables for incremental mapping
void Mapper::sortAllocTilesByLevel(CGRA* t_cgra){
map<int, vector<CGRANode*>> FanIO_CGRANodes;
vector<int> FanIOs;
int numTiles = 0;
for (int i=0; i<t_cgra->getRows(); ++i) {
for (int j=0; j<t_cgra->getColumns(); ++j) {

// Records the number of FanIO for each tile.
CGRANode* currentCGRANode = t_cgra->nodes[i][j];
if (currentCGRANode->isDisabled()) continue; // only record tiles that have DFGNodes mapped
int FanIO = max(currentCGRANode->getInLinks()->size(), currentCGRANode->getOutLinks()->size());
FanIO_CGRANodes[FanIO].push_back(currentCGRANode);

// Records FanIO in the list if it appears for the first time
if (find(FanIOs.begin(), FanIOs.end(), FanIO) == FanIOs.end()) {
FanIOs.push_back(FanIO);
}

numTiles++;
}
}
std::sort(FanIOs.rbegin(), FanIOs.rend()); // Sorts FanIOs from big to small to automatically form the level

CGRANodes_sortedByLevel.clear();
for (int level = 0; level < FanIOs.size(); level++) {
int FanIO = FanIOs[level];
vector<CGRANode*> tiles = FanIO_CGRANodes[FanIO];
CGRANodes_sortedByLevel.push_back(tiles);
}
}

// Generates the placement recommendation list for current DFGNode by referencing its placement in the former mapping results
// Two principles: RPT & MBO
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate on these two principles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reference Placement Tendency (RPT): if DFGNode0 is mapped on CGRANode5 in the referenced mapping results, we believe it should have the tendency to be mapped on the CGRANode that has the same or the closest FanIO with CGRANode5, so that we don't need to iteratively call calcaulateCost() like in heuristicMapper(), which saves lots of time and therefore accelerating the mapping.

Minimize Bypass Operations (MBO): Bypass operations occupy the CGRALink resources and may lead to the decrease of mapping quality. Therefore, on the basis of RPT, we further calculate the number of bypass operations for each CGRANode candidate required to communicate with its predecessors, and the CGRANode with fewer bypass operations has the higher priority to be mapped.

An example
example
I will post the link of the whole paper after it's published

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, super clear!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plz just provide the full name for RPT and MBO for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has been corrected

list<CGRANode*> Mapper::placementGen(CGRA* t_cgra, DFGNode* t_dfgNode){
list<CGRANode*> placementRecommList;
CGRANode* refCGRANode = refMapRes[t_dfgNode];
list<DFGNode*>* predNodes = t_dfgNode->getPredNodes();
int refLevel = CGRANodeID2Level[refCGRANode->getID()];
int level = refLevel;
int maxLevel = CGRANodes_sortedByLevel.size() - 1;
cout<<t_dfgNode->getOpcodeName()<<t_dfgNode->getID()<<" is mapped to Tile "<<refCGRANode->getID()<<" in the referenced mapping results, refLevel="<<refLevel<<endl;

int initLevel = level;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If level indicates the number of FanIO, why not just fanIO instead of level?

BTW, can we replace fanIO with inOutDegree? WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah these two variables are easily confused, I use the following examples to explain the difference:

map<int, vector<CGRANode*>> FanIO_CGRANodes = {
{4, {CGRANode5, CGRANode6, CGRANode9, CGRANode10}},
{3, {CGRANode1, CGRANode2, CGRANode4, CGRANode7, CGRANode8, CGRANode11, CGRANode13, CGRANode14}},
{2, {CGRANode0, CGRANode3, CGRANode12, CGRANode15}}
}
{CGRANode5, CGRANode6, CGRANode9, CGRANode10} all have FanIO=5 and Level=0
{CGRANode1, CGRANode2, CGRANode4, CGRANode7, CGRANode8, CGRANode11, CGRANode13, CGRANode14} all have FanIO=4 and Level=1
{CGRANode0, CGRANode3, CGRANode12, CGRANode15} all have FanIO=3 and Level=2

For an athelete in a championship, FanIO is his score, while Level is his ranking.

I thought I/O degree is for DFG and FanIO for CGRA?
ISCA2023_MapZero
Xiangyu Kong, Yi Huang, Jianfeng Zhu, Xingchen Man, Yang Liu, Chunyang Feng, Pengfei Gou, Minggui Tang, Shaojun Wei, and Leibo Liu. 2023. MapZero: Mapping for Coarse-grained Reconfigurable Architectures with Reinforcement Learning and Monte-Carlo Tree Search. In Proceedings of the 50th Annual International Symposium on Computer Architecture (ISCA '23). Association for Computing Machinery, New York, NY, USA, Article 46, 1–14. https://doi.org/10.1145/3579371.3589081

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, i am okay with FanIO. Can you rename level to priority? I still think we can just compare FanIO without using level or priority, which is more straightforward to me (i.e., larger FanIO has higher priority), level is just reversing their original ordering. Either way is fine, you can make the call. Just plz let me now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Larger FanIO not always has higher priority, for example in the referenced mapping results, DFGNode10 is mapped to CGRANode4 that has FanIO=4, which is a middle level of FanIO because we also have CGRANodes whose FanIO=3 and FanIO=5 under 4x4 CGRA.

So when incrementalMap() choose which CGRANodes within the new resource allocation decision have highest priority for DFGNode10 to map on, those CGRANodes with the middle level of FanIO will be selected. And the middle level of FanIO may not always equal to 4, for example in the new resource allocation decision shown in the follow image, the middle level of FanIO is 2 (Others levels are FanIO=1 and FanIO=3).
example
Comparing the FanIO may mislead incrementalMap() to select the CGRANodes with FanIO=3 if you think larger FanIO has higher priority?

So sorry I still think level may be more appropriate than priroity.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could there exist FanIO=5 under 4x4 CGRA? I assume you are talking about FanIO=4. It sounds like you are ordering the tiles based on how their FanIO is closed to the FanIO of the tile the DFGNode was originally mapped on. Can you please schedule a 20min one-on-one meeting with me?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plz add comment "The level is used to ordering the CGRANodes based on the FanIO. Though FanIO of each CGRANode would change for different CGRA architectures, the DFGNode prefers to being mapped onto the CGRANode with same level."

while (true) {
map<int, vector<CGRANode*>> bypassNums_CGRANode;
int curX, curY, preX, preY;
int xdiff, ydiff;
for (auto curCGRANode : CGRANodes_sortedByLevel[level]) {
int numBypass = 0;
for (DFGNode* pre: *predNodes) {
if (m_mapping.find(pre) != m_mapping.end()) {
CGRANode* preCGRANode = m_mapping[pre];
xdiff = abs(curCGRANode->getX() - preCGRANode->getX());
ydiff = abs(curCGRANode->getY() - preCGRANode->getY());
numBypass += (xdiff + ydiff);
}
else continue;
}
bypassNums_CGRANode[numBypass].push_back(curCGRANode);
}

// bypassNums_CGRANode is sorted by key from smallest to largest by default, and tile with fewer bypass nodes has higher priority
for (auto iter : bypassNums_CGRANode) {
for (auto tile : iter.second) {
placementRecommList.push_back(tile);
}
}

level += 1;
if (level > maxLevel) {
level = 0; // Goes back to the highest level
}
if (level == initLevel) break;
}

return placementRecommList;
}

// Incremental mapping function
int Mapper::incrementalMap(CGRA* t_cgra, DFG* t_dfg, int t_II){
if (readRefMapRes(t_cgra, t_dfg) == -1) return -1;
sortAllocTilesByLevel(t_cgra);

bool dfgNodeMapFailed;
while (1) {
cout<<"----------------------------------------\n";
cout<<"[DEBUG] start incremental mapping with II="<<t_II<<"\n";
int cycle = 0;
constructMRRG(t_dfg, t_cgra, t_II);
for (list<DFGNode*>::iterator dfgNode=t_dfg->nodes.begin(); dfgNode!=t_dfg->nodes.end(); dfgNode++) {
list<CGRANode*> placementRecommList = placementGen(t_cgra, *dfgNode);
dfgNodeMapFailed = true;
for (auto fu : placementRecommList) {
map<CGRANode*, int>* path = calculateCost(t_cgra, t_dfg, t_II, *dfgNode, fu);
if (path == NULL) {
cout<<"[DEBUG] no available path for DFG node "<<(*dfgNode)->getID()<<" on CGRA node "<<fu->getID()<<" within II "<<t_II<<endl;
continue; // Switches to next tile in placementRecommList
}
else {
if (schedule(t_cgra, t_dfg, t_II, *dfgNode, path, false)) {
dfgNodeMapFailed = false;
break; // Current DFGNode finishes mapping, move to next DFGNode
}
else {
cout<<"[DEBUG] no available path to schedule DFG node "<<(*dfgNode)->getID()<<" on CGRA node "<<fu->getID()<<" within II "<<t_II<<endl;
continue; // Switches to next tile in placementRecommList
}
}
}
if (dfgNodeMapFailed) break; // Current DFGNode fails mapping, increase II and restart
}

if (dfgNodeMapFailed) {
cout<<"[DEBUG] fail in schedule() under II: "<<t_II<<"\n";
t_II++;
}
else {
cout<<"[DEBUG] success in schedule() under II: "<<t_II<<"\n";
return t_II;
}
}

return -1;
}

8 changes: 8 additions & 0 deletions src/Mapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class Mapper {
bool DFSMap(CGRA*, DFG*, int, list<DFGNode*>*, list<map<CGRANode*, int>*>*, bool);
list<map<CGRANode*, int>*>* getOrderedPotentialPaths(CGRA*, DFG*, int,
DFGNode*, list<map<CGRANode*, int>*>*);
map<DFGNode*, CGRANode*> refMapRes;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plz comment on refMapRes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refMapRes is short for reference mapping results, which contains the mapping relationship between each DFGNode and CGRANode

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reference mapping indicates the original mapping read from the .json, right?

When I say comment on, I mean provide the // Provides comments above the corresponding code. Thanks~!

Copy link
Contributor Author

@yyan7223 yyan7223 Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then plz add the comments above it.

map<int, int> CGRANodeID2Level;
vector<vector<CGRANode*>> CGRANodes_sortedByLevel;

public:
Mapper(){}
Expand All @@ -40,4 +43,9 @@ class Mapper {
bool schedule(CGRA*, DFG*, int, DFGNode*, map<CGRANode*, int>*, bool);
void showSchedule(CGRA*, DFG*, int, bool, bool);
void generateJSON(CGRA*, DFG*, int, bool);
void generateJSON4IncrementalMap(CGRA*, DFG*);
int readRefMapRes(CGRA*, DFG*);
void sortAllocTilesByLevel(CGRA*);
list<CGRANode*> placementGen(CGRA*, DFGNode*);
int incrementalMap(CGRA*, DFG*, int);
};
31 changes: 27 additions & 4 deletions src/mapperPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
using namespace llvm;
using namespace std;
using json = nlohmann::json;
using namespace chrono;

void addDefaultKernels(map<string, list<int>*>*);

Expand Down Expand Up @@ -57,7 +58,8 @@ namespace {
bool diagonalVectorization = false;
bool heterogeneity = false;
bool heuristicMapping = true;
bool parameterizableCGRA = false;
bool parameterizableCGRA = false;
bool incrementalMapping = false;
map<string, int>* execLatency = new map<string, int>();
list<string>* pipelinedOpt = new list<string>();
map<string, list<int>*>* additionalFunc = new map<string, list<int>*>();
Expand Down Expand Up @@ -97,6 +99,7 @@ namespace {
paramKeys.insert("heterogeneity");
paramKeys.insert("heuristicMapping");
paramKeys.insert("parameterizableCGRA");
paramKeys.insert("incrementalMapping");

try
{
Expand Down Expand Up @@ -135,6 +138,7 @@ namespace {
heterogeneity = param["heterogeneity"];
heuristicMapping = param["heuristicMapping"];
parameterizableCGRA = param["parameterizableCGRA"];
incrementalMapping = param["incrementalMapping"];
cout<<"Initialize opt latency for DFG nodes: "<<endl;
for (auto& opt : param["optLatency"].items()) {
cout<<opt.key()<<" : "<<opt.value()<<endl;
Expand Down Expand Up @@ -211,13 +215,26 @@ namespace {
bool success = false;
if (!isStaticElasticCGRA) {
cout << "==================================\n";
typedef std::chrono::high_resolution_clock Clock;
auto t1 = Clock::now();

if (heuristicMapping) {
cout << "[heuristic]\n";
II = mapper->heuristicMap(cgra, dfg, II, isStaticElasticCGRA);
if(incrementalMapping){
II = mapper->incrementalMap(cgra, dfg, II);
cout << "[Incremental]\n";
}
else{
cout << "[heuristic]\n";
II = mapper->heuristicMap(cgra, dfg, II, isStaticElasticCGRA);
}
} else {
cout << "[exhaustive]\n";
II = mapper->exhaustiveMap(cgra, dfg, II, isStaticElasticCGRA);
}

auto t2 = Clock::now();
int elapsedTime = std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() / 1000000;
std::cout <<"Mapping algorithm elapsed time="<<elapsedTime <<"ms"<< '\n';
}

// Partially exhaustive search to try to map the DFG onto
Expand All @@ -238,7 +255,13 @@ namespace {
cout << "[Mapping Success]\n";
cout << "==================================\n";
mapper->generateJSON(cgra, dfg, II, isStaticElasticCGRA);
cout << "[Output Json]\n";
cout << "[Output Json]\n";

// save mapping results json file for possible incremental mapping
if(!incrementalMapping) {
mapper->generateJSON4IncrementalMap(cgra, dfg);
cout << "[Output Json for Incremental Mapping]\n";
}
}
cout << "=================================="<<endl;

Expand Down
3 changes: 2 additions & 1 deletion test/param.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"additionalFunc" : {
"load" : [4],
"store": [4]
}
},
"incrementalMapping" : false
}