Xplace_for_ICCAD/cpp_to_py/gpugr/gr/PatternRoute.cu

1215 lines
67 KiB
Plaintext
Raw Normal View History

2023-04-06 13:34:26 +08:00
#include <iostream>
#include <map>
#include "PatternRoute.h"
namespace gr {
__managed__ int debug;
#define INF 1000000000
__global__ void initMap(int *map) { map[blockIdx.x * blockDim.x + threadIdx.x] = INF; }
template <typename T>
__device__ void inline cudaSwap(T &a, T &b) {
T c(a);
a = b;
b = c;
}
__device__ void viaSweep(int *map, int *prev, int *viaCost, int x, int y, int LAYER, int N, int DIRECTION) {
map += 4 * LAYER * N * N;
prev += 4 * LAYER * N * N;
for (int i = 1; i < LAYER; i++) {
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
prev[cur + LAYER * N * N] = cur;
}
for (int i = 2; i < LAYER; i++) {
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int last = (i - 1) * N * N + (((i & 1) ^ DIRECTION) ? y * N + x : x * N + y);
if (map[cur] > map[last] + viaCost[last])
map[cur] = map[last] + viaCost[last], prev[cur] = prev[last], prev[cur + LAYER * N * N] = last;
}
for (int i = LAYER - 2; i >= 1; i--) {
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int last = (i + 1) * N * N + (((i & 1) ^ DIRECTION) ? y * N + x : x * N + y);
if (map[cur] > map[last] + viaCost[cur])
map[cur] = map[last] + viaCost[cur], prev[cur] = prev[last], prev[cur + LAYER * N * N] = last;
}
}
__global__ void cudaLshapePR(int *map,
int *points,
int64_t *wireCostSum,
int *viaCost,
int *prev,
int *wires,
int *vias,
int *routes,
int LAYER,
int N,
int DIRECTION) {
// printf("%d offset %d\n", threadIdx.x, points[threadIdx.x]);
points += points[blockIdx.x];
routes += points[0];
routes[0] = 1;
int node_cnt = points[1];
points += 2;
for (int t = 6 * (node_cnt - 1); t >= 0; t -= 6) {
int tox = points[t] / N, toy = points[t] % N, minlayer = points[t + 1], maxlayer = points[t + 2];
/*if(points[t + 3] == -1)
printf("no child\n");
else
printf("child!\n");*/
for (int j = 1; j <= 3; j++)
if (points[t + 2 + j] != -1) {
int fromx = points[t + 2 + j] / N, fromy = points[t + 2 + j] % N;
// printf("%d %d to %d %d\n", fromx, fromy, tox, toy);
if (fromx != tox && fromy != toy) {
for (int i = 0; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION)
map[4 * LAYER * N * N + i * N * N + fromx * N + toy] =
map[4 * LAYER * N * N + i * N * N + tox * N + fromy] = INF;
else
map[4 * LAYER * N * N + i * N * N + toy * N + fromx] =
map[4 * LAYER * N * N + i * N * N + fromy * N + tox] = INF;
}
for (int i = 1; i < LAYER; i++) {
int last = i * N * N + (((i & 1) ^ DIRECTION) ? fromx * N + fromy : fromy * N + fromx);
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? fromx * N + toy : fromy * N + tox);
int cost =
last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + cur] > map[last] + cost)
map[4 * LAYER * N * N + cur] = map[last] + cost, prev[4 * LAYER * N * N + cur] = last;
}
viaSweep(map, prev, viaCost, fromx, toy, LAYER, N, DIRECTION);
viaSweep(map, prev, viaCost, tox, fromy, LAYER, N, DIRECTION);
for (int i = 1; i < LAYER; i++) {
int last = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + fromy : toy * N + fromx);
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
int cost =
last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[4 * LAYER * N * N + last] + cost)
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost,
prev[cur + j * LAYER * N * N] = prev[4 * LAYER * N * N + last];
}
} else if (fromx == tox) {
for (int i = 1; i < LAYER; i++)
if ((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy, cur = i * N * N + tox * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost)
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
}
} else if (fromy == toy) {
for (int i = 1; i < LAYER; i++)
if (!(i & 1) ^ DIRECTION) {
int last = i * N * N + fromy * N + fromx, cur = i * N * N + toy * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost)
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
}
} else
printf("ERROR: points on the same location!\n");
}
if (debug) printf("\n");
for (int lower = 0; lower < LAYER; lower++) {
int viaSum = 0, minCost = INF, bestpos[3] = {0, 0, 0},
costs[3] = {
points[t + 3] == -1 ? 0 : INF, points[t + 4] == -1 ? 0 : INF, points[t + 5] == -1 ? 0 : INF};
for (int upper = lower; upper < LAYER; upper++) {
int idx = upper * N * N + (((upper & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
for (int j = 0; j < 3; j++)
if (points[t + 3 + j] != -1) {
if (map[idx + (j + 1) * LAYER * N * N] < costs[j])
costs[j] = map[idx + (j + 1) * LAYER * N * N], bestpos[j] = upper;
}
// if(upper == 0)
// printf("cost[0] = %d\n", costs[0]);
if (1LL * costs[0] + costs[1] + costs[2] < minCost) minCost = costs[0] + costs[1] + costs[2];
if (minlayer == -1 || (lower <= minlayer && maxlayer <= upper)) {
// printf("upper %d viaSUm %d\n", upper, viaSum);
for (int i = lower; i <= upper; i++) {
int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
if (map[index] > minCost + viaSum)
map[index] = minCost + viaSum,
prev[index] =
(((lower * LAYER + upper) * LAYER + bestpos[2]) * LAYER + bestpos[1]) * LAYER +
bestpos[0];
}
}
viaSum += viaCost[idx];
}
}
// for (int i = 0; i < LAYER; i++) {
// int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
// int lower = prev[index] / LAYER / LAYER / LAYER / LAYER,
// upper = prev[index] / LAYER / LAYER / LAYER % LAYER;
// // printf("layer %d, cost %d, lower %d, upper %d, bestpos %d\n", i, map[index], lower, upper, prev[index]
// %
// // LAYER);
// }
}
int minTotalDist = INF;
for (int i = 0; i < LAYER; i++) {
int x = points[0] / N, y = points[0] % N;
int idx = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
if (map[idx] < minTotalDist) minTotalDist = map[idx], map[4 * LAYER * N * N + points[0]] = i;
}
if (minTotalDist == INF || minTotalDist < 0) {
printf("INF is too small!\n");
return;
}
for (int t = 0; t < 6 * node_cnt; t += 6) {
int x = points[t] / N, y = points[t] % N, layer = map[4 * LAYER * N * N + points[t]];
int idx = layer * N * N + (((layer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int minlayer = prev[idx] / LAYER / LAYER / LAYER / LAYER, maxlayer = prev[idx] / LAYER / LAYER / LAYER % LAYER;
// printf("%d [%d, %d] exit/min/max layer\n", layer, minlayer, maxlayer);
for (int i = minlayer; i < maxlayer; i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
int bestpos = prev[idx];
for (int j = 0; j < 3; j++) {
int child = points[t + 3 + j];
if (points[t + 3 + j] == -1) break;
int entrylayer = bestpos % LAYER,
entry = entrylayer * N * N + (((entrylayer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
// printf("(%d, %d, %d) ", entrylayer, x, y);
bestpos /= LAYER;
int last = prev[(j + 1) * LAYER * N * N + entry];
int lastlayer = last / N / N, lastx = last / N % N, lasty = last % N;
if (!(lastlayer & 1) ^ DIRECTION) cudaSwap(lastx, lasty);
if (lastx != x && lasty != y) {
int _x = ((entrylayer & 1) ^ DIRECTION) ? x : lastx;
int _y = ((entrylayer & 1) ^ DIRECTION) ? lasty : y;
int p1 = ((entrylayer & 1) ^ DIRECTION) ? entry - y + lasty : entry - x + lastx;
int p2 = ((lastlayer & 1) ^ DIRECTION) ? last - lasty + y : last - lastx + x;
routes[routes[0]++] = min(entry, p1);
routes[routes[0]++] = max(entry, p1) - min(entry, p1);
for (int i = min(entry, p1); i < max(entry, p1); i++) atomicAdd(wires + i, 1);
routes[routes[0]++] = min(last, p2);
routes[routes[0]++] = max(last, p2) - min(last, p2);
for (int i = min(last, p2); i < max(last, p2); i++) atomicAdd(wires + i, 1);
for (int i = min(lastlayer, entrylayer); i < max(lastlayer, entrylayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? _x * N + _y : _y * N + _x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
} else {
routes[routes[0]++] = min(last, entry);
routes[routes[0]++] = max(last, entry) - min(last, entry);
for (int i = min(last, entry); i < max(last, entry); i++) atomicAdd(wires + i, 1);
}
// if(x == 46 && y == 47)
// printf("(%d %d %d) <- (%d %d %d)\n", entrylayer, entry / N % N, entry % N, last / N / N, last / N %
// N, last % N);
map[4 * LAYER * N * N + child] = lastlayer;
}
}
if (debug)
for (int i = 1; i < routes[0]; i += 2) {
int layer = routes[i] / N / N, x = routes[i] / N % N, y = routes[i] % N;
if ((layer & 1) ^ DIRECTION) {
if (routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer + 1, x, y);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if (routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer + 1, y, x);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer, y + routes[i + 1], x);
}
/*if((layer & 1) ^ DIRECTION) {
if(routes[i + 1] == -1)
printf("[%d, %d, %d], [%d, %d, %d], ", layer, x, y, layer + 1, x, y);
else
printf("[%d, %d, %d], [%d, %d, %d], ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if(routes[i + 1] == -1)
printf("[%d, %d, %d], [%d, %d, %d], ", layer, y, x, layer + 1, y, x);
else
printf("[%d, %d, %d], [%d, %d, %d], ", layer, y, x, layer, y + routes[i + 1], x);
}*/
}
}
#define FLAG -1
__global__ void cudaPatternRoute(int *map,
int *points,
int64_t *wireCostSum,
int *viaCost,
int *prev,
int *prev2,
int *wires,
int *vias,
int *routes,
int LAYER,
int N,
int DIRECTION) {
// printf("%d offset %d\n", threadIdx.x, points[threadIdx.x]);
points += points[blockIdx.x];
routes += points[0];
routes[0] = 1;
int node_cnt = points[1];
points += 2;
for (int t = 6 * (node_cnt - 1); t >= 0; t -= 6) {
int tox = points[t] / N, toy = points[t] % N, minlayer = points[t + 1], maxlayer = points[t + 2];
// if(points[-2] == FLAG) printf("POINT (%d, %d)\n", tox, toy);
/*if(points[t + 3] == -1)
printf("no child\n");
else
printf("child!\n");*/
for (int j = 1; j <= 3; j++)
if (points[t + 2 + j] != -1) {
int fromx = points[t + 2 + j] / N, fromy = points[t + 2 + j] % N;
if (fromx != tox && fromy != toy) {
// if(max(fromx, tox) - min(fromx, tox) > 3 && max(fromy, toy) - min(fromy, toy) > 3) printf("%d %d
// largeto %d %d\n", fromx, fromy, tox, toy);
for (int a = min(fromx, tox); a <= max(fromx, tox); a++)
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
map[4 * LAYER * N * N + i * N * N + a * N + toy] = INF;
map[4 * LAYER * N * N + i * N * N + a * N + fromy] = INF;
} else {
map[4 * LAYER * N * N + i * N * N + toy * N + a] = INF;
map[4 * LAYER * N * N + i * N * N + fromy * N + a] = INF;
}
}
for (int b = min(fromy, toy); b <= max(fromy, toy); b++)
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
map[4 * LAYER * N * N + i * N * N + tox * N + b] = INF;
map[4 * LAYER * N * N + i * N * N + fromx * N + b] = INF;
} else {
map[4 * LAYER * N * N + i * N * N + b * N + tox] = INF;
map[4 * LAYER * N * N + i * N * N + b * N + fromx] = INF;
}
}
for (int i = 1; i < LAYER; i++)
if ((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy;
for (int b = min(fromy, toy); b <= max(fromy, toy); b++)
if (b != fromy) {
int cur = i * N * N + fromx * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
map[4 * LAYER * N * N + cur] = map[last] + cost;
prev[4 * LAYER * N * N + cur] = last;
// printf("(%d, %d, %d) %d\n", i, fromx, b, map[4 * LAYER * N * N + cur]);
}
} else {
int last = i * N * N + fromy * N + fromx;
for (int b = min(fromx, tox); b <= max(fromx, tox); b++)
if (b != fromx) {
int cur = i * N * N + fromy * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
map[4 * LAYER * N * N + cur] = map[last] + cost;
prev[4 * LAYER * N * N + cur] = last;
// printf("(%d, %d, %d) %d\n", i, b, fromy, map[4 * LAYER * N * N + cur]);
}
}
for (int b = min(fromy, toy); b <= max(fromy, toy); b++)
if (b != fromy) viaSweep(map, prev, viaCost, fromx, b, LAYER, N, DIRECTION);
for (int b = min(fromx, tox); b <= max(fromx, tox); b++)
if (b != fromx) viaSweep(map, prev, viaCost, b, fromy, LAYER, N, DIRECTION);
for (int i = 1; i < LAYER; i++)
if ((i & 1) ^ DIRECTION) {
for (int b = min(fromx, tox); b <= max(fromx, tox); b++) {
int last = i * N * N + b * N + fromy, cur = i * N * N + b * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[4 * LAYER * N * N + cur]) {
map[4 * LAYER * N * N + cur] = map[4 * LAYER * N * N + last] + cost;
prev[4 * LAYER * N * N + cur] = prev[4 * LAYER * N * N + last];
}
}
} else {
for (int b = min(fromy, toy); b <= max(fromy, toy); b++) {
int last = i * N * N + b * N + fromx, cur = i * N * N + b * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[4 * LAYER * N * N + cur]) {
map[4 * LAYER * N * N + cur] = map[4 * LAYER * N * N + last] + cost;
prev[4 * LAYER * N * N + cur] = prev[4 * LAYER * N * N + last];
}
}
}
for (int b = min(fromy, toy); b <= max(fromy, toy); b++)
if (b != toy) viaSweep(map, prev, viaCost, tox, b, LAYER, N, DIRECTION);
for (int b = min(fromx, tox); b <= max(fromx, tox); b++)
if (b != tox) viaSweep(map, prev, viaCost, b, toy, LAYER, N, DIRECTION);
for (int i = 1; i < LAYER; i++)
if ((i & 1) ^ DIRECTION) {
int cur = i * N * N + tox * N + toy;
for (int b = min(fromy, toy); b <= max(fromy, toy); b++)
if (b != toy) {
int last = i * N * N + tox * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[cur + j * LAYER * N * N]) {
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost;
prev[cur + j * LAYER * N * N] = prev[4 * LAYER * N * N + last];
prev2[cur + j * LAYER * N * N] = prev[5 * LAYER * N * N + last];
}
}
} else {
int cur = i * N * N + toy * N + tox;
for (int b = min(fromx, tox); b <= max(fromx, tox); b++)
if (b != tox) {
int last = i * N * N + toy * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[cur + j * LAYER * N * N]) {
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost;
prev[cur + j * LAYER * N * N] = prev[4 * LAYER * N * N + last];
prev2[cur + j * LAYER * N * N] = prev[5 * LAYER * N * N + last];
}
}
}
} else if (fromx == tox) {
for (int i = 1; i < LAYER; i++)
if ((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy, cur = i * N * N + tox * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost)
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
} else
map[i * N * N + tox * N + toy + j * LAYER * N * N] = INF;
} else if (fromy == toy) {
for (int i = 1; i < LAYER; i++)
if (!(i & 1) ^ DIRECTION) {
int last = i * N * N + fromy * N + fromx, cur = i * N * N + toy * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost) {
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
}
} else {
map[i * N * N + toy * N + tox + j * LAYER * N * N] = INF;
}
} else
printf("ERROR: points on the same location!\n");
}
if (debug) printf("\n");
for (int lower = 0; lower < LAYER; lower++) {
int viaSum = 0, minCost = INF, bestpos[3] = {0, 0, 0},
costs[3] = {
points[t + 3] == -1 ? 0 : INF, points[t + 4] == -1 ? 0 : INF, points[t + 5] == -1 ? 0 : INF};
for (int upper = lower; upper < LAYER; upper++) {
int idx = upper * N * N + (((upper & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
for (int j = 0; j < 3; j++)
if (points[t + 3 + j] != -1) {
if (map[idx + (j + 1) * LAYER * N * N] < costs[j])
costs[j] = map[idx + (j + 1) * LAYER * N * N], bestpos[j] = upper;
}
if (1LL * costs[0] + costs[1] + costs[2] < minCost) minCost = costs[0] + costs[1] + costs[2];
if (minlayer == -1 || (lower <= minlayer && maxlayer <= upper)) {
for (int i = lower; i <= upper; i++) {
int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
if (map[index] > minCost + viaSum)
map[index] = minCost + viaSum,
prev[index] =
(((lower * LAYER + upper) * LAYER + bestpos[2]) * LAYER + bestpos[1]) * LAYER +
bestpos[0];
}
}
viaSum += viaCost[idx];
}
}
/*if(0) for(int i = 0; i < LAYER; i++) {
int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
int lower = prev[index] / LAYER / LAYER / LAYER / LAYER, upper = prev[index] / LAYER / LAYER / LAYER %
LAYER; printf("layer %d, cost %d, lower %d, upper %d, bestpos %d\n", i, map[index], lower, upper, prev[index] %
LAYER);
}*/
}
int minTotalDist = INF;
for (int i = 0; i < LAYER; i++) {
int x = points[0] / N, y = points[0] % N;
int idx = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
if (map[idx] < minTotalDist) minTotalDist = map[idx], map[4 * LAYER * N * N + points[0]] = i;
}
// if(points[-2] == FLAG) printf("min total dist %d\n", minTotalDist);
if (minTotalDist == INF || minTotalDist < 0) {
printf("INF is too small!\n");
printf("routes[0] = %d\n", points[-2]);
return;
}
for (int t = 0; t < 6 * node_cnt; t += 6) {
int x = points[t] / N, y = points[t] % N, layer = map[4 * LAYER * N * N + points[t]];
// printf("point (%d, %d)\n", x, y);
int idx = layer * N * N + (((layer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int minlayer = prev[idx] / LAYER / LAYER / LAYER / LAYER, maxlayer = prev[idx] / LAYER / LAYER / LAYER % LAYER;
// printf("layer range [%d, %d]\n", minlayer, maxlayer);
for (int i = minlayer; i < maxlayer; i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
int bestpos = prev[idx];
for (int j = 0; j < 3; j++) {
int child = points[t + 3 + j];
if (points[t + 3 + j] == -1) break;
int entrylayer = bestpos % LAYER,
entry = entrylayer * N * N + (((entrylayer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
// printf("(%d, %d, %d) ", entrylayer, x, y);
bestpos /= LAYER;
int last = prev[(j + 1) * LAYER * N * N + entry];
int lastlayer = last / N / N, lastx = last / N % N, lasty = last % N;
if (!(lastlayer & 1) ^ DIRECTION) cudaSwap(lastx, lasty);
if (lastx != x && lasty != y) {
int mid = prev2[(j + 1) * LAYER * N * N + entry];
int midlayer = mid / N / N, midx = mid / N % N, midy = mid % N;
if (!(midlayer & 1) ^ DIRECTION) cudaSwap(midx, midy);
// printf("%d (%d, %d, %d) %d\n", entrylayer, midlayer, midx, midy, lastlayer);
// entry-(wire)->p1-(via)->mid-(wire)->p3-(via)->p4-(wire)->last
int p1 = ((entrylayer & 1) ^ DIRECTION) ? entry - y + midy : entry - x + midx;
int p3 = ((midlayer & 1) ^ DIRECTION) ? mid - midy + lasty : mid - midx + lastx;
int p4 = ((lastlayer & 1) ^ DIRECTION) ? last - lasty + midy : last - lastx + midx;
/*printf("child %d of %d, ", j, t);
{
int temp = entry;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d) -> ", templayer, tempx, tempy);
}
{
int temp = p1;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d) -> ", templayer, tempx, tempy);
}
{
int temp = mid;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d) -> ", templayer, tempx, tempy);
}
{
int temp = p3;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d) -> ", templayer, tempx, tempy);
}
{
int temp = p4;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d) -> ", templayer, tempx, tempy);
}
{
int temp = last;
int templayer = temp / N / N, tempx = temp / N % N, tempy = temp % N;
if(!(templayer & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
printf("(%d, %d, %d)\n", templayer, tempx, tempy);
}
int cur = routes[0];*/
if (entry != p1) {
routes[routes[0]++] = min(entry, p1);
routes[routes[0]++] = max(entry, p1) - min(entry, p1);
for (int i = min(entry, p1); i < max(entry, p1); i++) atomicAdd(wires + i, 1);
}
if (p1 != mid) {
for (int i = min(entrylayer, midlayer); i < max(entrylayer, midlayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? midx * N + midy : midy * N + midx);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
}
if (mid != p3) {
routes[routes[0]++] = min(mid, p3);
routes[routes[0]++] = max(mid, p3) - min(mid, p3);
for (int i = min(mid, p3); i < max(mid, p3); i++) atomicAdd(wires + i, 1);
}
if (p3 != p4) {
int tempx = p3 / N % N, tempy = p3 % N;
if (!(p3 / N / N & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
for (int i = min(midlayer, lastlayer); i < max(midlayer, lastlayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? tempx * N + tempy : tempy * N + tempx);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
}
if (p4 != last) {
routes[routes[0]++] = min(p4, last);
routes[routes[0]++] = max(p4, last) - min(p4, last);
for (int i = min(p4, last); i < max(p4, last); i++) atomicAdd(wires + i, 1);
}
/*for(int i = cur; i < routes[0]; i += 2) {
int layer = routes[i] / N / N, x = routes[i] / N % N, y = routes[i] % N;
if((layer & 1) ^ DIRECTION) {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer + 1, x, y);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer + 1, y, x);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer, y + routes[i + 1], x);
}
}
printf("\n");*/
} else {
routes[routes[0]++] = min(last, entry);
routes[routes[0]++] = max(last, entry) - min(last, entry);
for (int i = min(last, entry); i < max(last, entry); i++) atomicAdd(wires + i, 1);
}
map[4 * LAYER * N * N + child] = lastlayer;
}
}
if (debug)
for (int i = 1; i < routes[0]; i += 2) {
int layer = routes[i] / N / N, x = routes[i] / N % N, y = routes[i] % N;
if ((layer & 1) ^ DIRECTION) {
if (routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer + 1, x, y);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if (routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer + 1, y, x);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer, y + routes[i + 1], x);
}
}
// printf("\n");
}
__global__ void cudaPatternRouteParallel(int *map,
int *points,
int64_t *wireCostSum,
int *viaCost,
int *prev,
int *prev2,
int *wires,
int *vias,
int *routes,
int *gbpoints,
int *gbpinRoutes,
int LAYER,
int N,
int DIRECTION) {
// printf("%d offset %d\n", threadIdx.x, points[threadIdx.x]);
gbpoints += gbpoints[blockIdx.x];
points += points[blockIdx.x];
routes += points[0];
if (threadIdx.x == 0) routes[0] = 1;
__syncthreads();
int node_cnt = points[1];
points += 2;
for (int t = 6 * (node_cnt - 1); t >= 0; t -= 6) {
int tox = points[t] / N, toy = points[t] % N, minlayer = points[t + 1], maxlayer = points[t + 2];
for (int j = 1; j <= 3; j++) {
if (points[t + 2 + j] != -1) {
int childPos = points[points[t + 2 + j]];
int fromx = childPos / N, fromy = childPos % N;
if (fromx != tox && fromy != toy) {
for (int a = min(fromx, tox) + threadIdx.x; a <= max(fromx, tox); a += blockDim.x) {
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
map[4 * LAYER * N * N + i * N * N + a * N + toy] = INF;
map[4 * LAYER * N * N + i * N * N + a * N + fromy] = INF;
} else {
map[4 * LAYER * N * N + i * N * N + toy * N + a] = INF;
map[4 * LAYER * N * N + i * N * N + fromy * N + a] = INF;
}
}
}
__syncthreads();
for (int b = min(fromy, toy) + threadIdx.x; b <= max(fromy, toy); b += blockDim.x) {
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
map[4 * LAYER * N * N + i * N * N + tox * N + b] = INF;
map[4 * LAYER * N * N + i * N * N + fromx * N + b] = INF;
} else {
map[4 * LAYER * N * N + i * N * N + b * N + tox] = INF;
map[4 * LAYER * N * N + i * N * N + b * N + fromx] = INF;
}
}
}
__syncthreads();
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy;
for (int b = min(fromy, toy) + threadIdx.x; b <= max(fromy, toy); b += blockDim.x) {
if (b != fromy) {
int cur = i * N * N + fromx * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
map[4 * LAYER * N * N + cur] = map[last] + cost;
prev[4 * LAYER * N * N + cur] = last;
}
}
} else {
int last = i * N * N + fromy * N + fromx;
for (int b = min(fromx, tox) + threadIdx.x; b <= max(fromx, tox); b += blockDim.x) {
if (b != fromx) {
int cur = i * N * N + fromy * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
map[4 * LAYER * N * N + cur] = map[last] + cost;
prev[4 * LAYER * N * N + cur] = last;
}
}
}
__syncthreads();
}
__syncthreads();
for (int b = min(fromy, toy) + threadIdx.x; b <= max(fromy, toy); b += blockDim.x)
if (b != fromy) viaSweep(map, prev, viaCost, fromx, b, LAYER, N, DIRECTION);
__syncthreads();
for (int b = min(fromx, tox) + threadIdx.x; b <= max(fromx, tox); b += blockDim.x)
if (b != fromx) viaSweep(map, prev, viaCost, b, fromy, LAYER, N, DIRECTION);
__syncthreads();
for (int i = 1; i < LAYER; i++) {
if ((i & 1) ^ DIRECTION) {
for (int b = min(fromx, tox) + threadIdx.x; b <= max(fromx, tox); b += blockDim.x) {
int last = i * N * N + b * N + fromy, cur = i * N * N + b * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[4 * LAYER * N * N + cur]) {
map[4 * LAYER * N * N + cur] = map[4 * LAYER * N * N + last] + cost;
prev[4 * LAYER * N * N + cur] = prev[4 * LAYER * N * N + last];
}
}
} else {
for (int b = min(fromy, toy) + threadIdx.x; b <= max(fromy, toy); b += blockDim.x) {
int last = i * N * N + b * N + fromx, cur = i * N * N + b * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[4 * LAYER * N * N + cur]) {
map[4 * LAYER * N * N + cur] = map[4 * LAYER * N * N + last] + cost;
prev[4 * LAYER * N * N + cur] = prev[4 * LAYER * N * N + last];
}
}
}
__syncthreads();
}
__syncthreads();
for (int b = min(fromy, toy) + threadIdx.x; b <= max(fromy, toy); b += blockDim.x)
if (b != toy) viaSweep(map, prev, viaCost, tox, b, LAYER, N, DIRECTION);
__syncthreads();
for (int b = min(fromx, tox) + threadIdx.x; b <= max(fromx, tox); b += blockDim.x)
if (b != tox) viaSweep(map, prev, viaCost, b, toy, LAYER, N, DIRECTION);
__syncthreads();
for (int i = 1 + threadIdx.x; i < LAYER; i += blockDim.x) {
if ((i & 1) ^ DIRECTION) {
int cur = i * N * N + tox * N + toy;
for (int b = min(fromy, toy); b <= max(fromy, toy); b++) {
if (b != toy) {
int last = i * N * N + tox * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[cur + j * LAYER * N * N]) {
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost;
prev[cur + j * LAYER * N * N] = prev[4 * LAYER * N * N + last];
prev2[cur + j * LAYER * N * N] = prev[5 * LAYER * N * N + last];
}
}
}
} else {
int cur = i * N * N + toy * N + tox;
for (int b = min(fromx, tox); b <= max(fromx, tox); b++) {
if (b != tox) {
int last = i * N * N + toy * N + b;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[4 * LAYER * N * N + last] + cost < map[cur + j * LAYER * N * N]) {
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost;
prev[cur + j * LAYER * N * N] = prev[4 * LAYER * N * N + last];
prev2[cur + j * LAYER * N * N] = prev[5 * LAYER * N * N + last];
}
}
}
}
}
__syncthreads();
} else if (fromx == tox) {
for (int i = 1 + threadIdx.x; i < LAYER; i += blockDim.x) {
if ((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy, cur = i * N * N + tox * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost)
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
} else {
map[i * N * N + toy * N + tox + j * LAYER * N * N] = INF;
}
}
__syncthreads();
} else if (fromy == toy) {
for (int i = 1 + threadIdx.x; i < LAYER; i += blockDim.x) {
if (!(i & 1) ^ DIRECTION) {
int last = i * N * N + fromy * N + fromx, cur = i * N * N + toy * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur]
: wireCostSum[cur] - wireCostSum[last];
if (map[cur + j * LAYER * N * N] > map[last] + cost) {
map[cur + j * LAYER * N * N] = map[last] + cost, prev[cur + j * LAYER * N * N] = last;
}
} else {
map[i * N * N + tox * N + toy + j * LAYER * N * N] = INF;
}
}
__syncthreads();
} else {
printf("ERROR: points on the same location!\n");
}
__syncthreads();
}
__syncthreads();
}
__syncthreads();
if (threadIdx.x == 0) {
for (int lower = 0; lower < LAYER; lower++) {
int viaSum = 0, minCost = INF, bestpos[3] = {0, 0, 0},
costs[3] = {
points[t + 3] == -1 ? 0 : INF, points[t + 4] == -1 ? 0 : INF, points[t + 5] == -1 ? 0 : INF};
for (int upper = lower; upper < LAYER; upper++) {
int idx = upper * N * N + (((upper & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
for (int j = 0; j < 3; j++)
if (points[t + 3 + j] != -1) {
if (map[idx + (j + 1) * LAYER * N * N] < costs[j])
costs[j] = map[idx + (j + 1) * LAYER * N * N], bestpos[j] = upper;
}
if (1LL * costs[0] + costs[1] + costs[2] < minCost) minCost = costs[0] + costs[1] + costs[2];
if (minlayer == -1 || (lower <= minlayer && maxlayer <= upper)) {
for (int i = lower; i <= upper; i++) {
int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
if (map[index] > minCost + viaSum)
map[index] = minCost + viaSum,
prev[index] =
(((lower * LAYER + upper) * LAYER + bestpos[2]) * LAYER + bestpos[1]) * LAYER +
bestpos[0];
}
}
// if(t == 0)
// printf("[%d, %d] best = %d, cost = %d, via=%d\n", lower, upper, prev[25025] % LAYER,
// costs[0], viaSum);
viaSum += viaCost[idx];
}
// if(t == 0)
// printf("mincost = %d, [%d, %d] bestpos = %d\n", minCost, minlayer, maxlayer, bestpos[0]);
}
}
__syncthreads();
}
__syncthreads();
if (threadIdx.x == 0) {
int minTotalDist = INF;
for (int i = 0; i < LAYER; i++) {
int x = points[0] / N, y = points[0] % N;
int idx = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
if (map[idx] < minTotalDist) {
minTotalDist = map[idx];
// TODO: use a N x N matrix to achieve pos2layer map so that the map size can be optimized
map[5 * LAYER * N * N + points[0]] = i;
// printf("layer = %d, idx=%d, bestpos = %d\n", i, idx, prev[idx] % LAYER);
}
}
if (minTotalDist == INF || minTotalDist < 0) {
printf("failed\n");
routes[0] = -1;
// printf("routes[0] = %d\n", points[-2]);
// return;
} else {
// printf("total cost %d, layer %d\n", minTotalDist, map[5 * LAYER * N * N + points[0]]);
for (int t = 0; t < 6 * node_cnt; t += 6) {
int t_gbPinId = gbpoints[t / 6];
int x = points[t] / N, y = points[t] % N, layer = map[5 * LAYER * N * N + points[t]];
int idx = layer * N * N + (((layer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int minlayer = prev[idx] / LAYER / LAYER / LAYER / LAYER,
maxlayer = prev[idx] / LAYER / LAYER / LAYER % LAYER;
for (int i = minlayer; i < maxlayer; i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
vias[id]++;
}
// Assign #vias to gbpinRoutes
if (t_gbPinId != -1) {
gbpinRoutes[t_gbPinId * 6 + 5] = maxlayer - minlayer;
}
// printf("best range [%d, %d]\n", minlayer, maxlayer);
int bestpos = prev[idx];
for (int j = 0; j < 3; j++) {
if (points[t + 3 + j] == -1) break;
int entry_routeId = -1, last_routeId = -1;
int child = points[points[t + 3 + j]];
int entrylayer = bestpos % LAYER,
entry = entrylayer * N * N + (((entrylayer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
// if(t == 0)
// printf("layer %d\n", entrylayer);
// printf("(%d, %d, %d) ", entrylayer, x, y);
bestpos /= LAYER;
int last = prev[(j + 1) * LAYER * N * N + entry];
int lastlayer = last / N / N, lastx = last / N % N, lasty = last % N;
if (!(lastlayer & 1) ^ DIRECTION) cudaSwap(lastx, lasty);
if (lastx != x && lasty != y) {
int mid = prev2[(j + 1) * LAYER * N * N + entry];
int midlayer = mid / N / N, midx = mid / N % N, midy = mid % N;
if (!(midlayer & 1) ^ DIRECTION) cudaSwap(midx, midy);
// printf("%d (%d, %d, %d) %d\n", entrylayer, midlayer, midx, midy, lastlayer);
// entry-(wire)->p1-(via)->mid-(wire)->p3-(via)->p4-(wire)->last
int p1 = ((entrylayer & 1) ^ DIRECTION) ? entry - y + midy : entry - x + midx;
int p3 = ((midlayer & 1) ^ DIRECTION) ? mid - midy + lasty : mid - midx + lastx;
int p4 = ((lastlayer & 1) ^ DIRECTION) ? last - lasty + midy : last - lastx + midx;
if (entry != p1) {
int encodeId = entry <= p1 ? routes[0] : -routes[0];
if (entry_routeId == -1) entry_routeId = encodeId;
last_routeId = encodeId;
routes[routes[0]++] = min(entry, p1);
routes[routes[0]++] = max(entry, p1) - min(entry, p1);
for (int i = min(entry, p1); i < max(entry, p1); i++) wires[i]++;
// atomicAdd(wires + i, 1);
}
if (p1 != mid) {
for (int i = min(entrylayer, midlayer); i < max(entrylayer, midlayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? midx * N + midy : midy * N + midx);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
vias[id]++;
// atomicAdd(vias + id, 1);
}
}
if (mid != p3) {
int encodeId = mid <= p3 ? routes[0] : -routes[0];
if (entry_routeId == -1) entry_routeId = encodeId;
last_routeId = encodeId;
routes[routes[0]++] = min(mid, p3);
routes[routes[0]++] = max(mid, p3) - min(mid, p3);
for (int i = min(mid, p3); i < max(mid, p3); i++) wires[i]++;
// atomicAdd(wires + i, 1);
}
if (p3 != p4) {
int tempx = p3 / N % N, tempy = p3 % N;
if (!(p3 / N / N & 1) ^ DIRECTION) cudaSwap(tempx, tempy);
for (int i = min(midlayer, lastlayer); i < max(midlayer, lastlayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? tempx * N + tempy : tempy * N + tempx);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
vias[id]++;
// atomicAdd(vias + id, 1);
}
}
if (p4 != last) {
int encodeId = p4 <= last ? routes[0] : -routes[0];
if (entry_routeId == -1) entry_routeId = encodeId;
last_routeId = encodeId;
routes[routes[0]++] = min(p4, last);
routes[routes[0]++] = max(p4, last) - min(p4, last);
for (int i = min(p4, last); i < max(p4, last); i++) wires[i]++;
// atomicAdd(wires + i, 1);
}
} else {
int encodeId = entry <= last ? routes[0] : -routes[0];
if (entry_routeId == -1) entry_routeId = encodeId;
last_routeId = encodeId;
routes[routes[0]++] = min(last, entry);
routes[routes[0]++] = max(last, entry) - min(last, entry);
for (int i = min(last, entry); i < max(last, entry); i++) wires[i]++;
// atomicAdd(wires + i, 1);
}
map[5 * LAYER * N * N + child] = lastlayer;
// Assign entry/last route to gbpinRoutes
if (t_gbPinId != -1) {
gbpinRoutes[t_gbPinId * 6 + 1 + gbpinRoutes[t_gbPinId * 6]] = entry_routeId;
gbpinRoutes[t_gbPinId * 6]++;
if (gbpinRoutes[t_gbPinId * 6] > 4) {
printf("Error: numRoutes for t_gbpin d%d\n", gbpinRoutes[t_gbPinId * 6]);
}
}
int c_gbPinId = gbpoints[points[t + 3 + j] / 6];
if (c_gbPinId != -1) {
// negative routeId to refer the last route
gbpinRoutes[c_gbPinId * 6 + 1 + gbpinRoutes[c_gbPinId * 6]] = -1 * last_routeId;
gbpinRoutes[c_gbPinId * 6]++;
if (gbpinRoutes[c_gbPinId * 6] > 4) {
printf("Error: numRoutes for c_gbpin %d\n", gbpinRoutes[c_gbPinId * 6]);
}
}
}
}
}
/*for(int i = 1; i < routes[0]; i += 2) {
int layer = routes[i] / N / N, x = routes[i] / N % N, y = routes[i] % N;
if((layer & 1) ^ DIRECTION) {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer + 1, x, y);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer + 1, y, x);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer, y + routes[i + 1], x);
}
}
printf("\n");*/
}
__syncthreads();
/*__syncthreads();
for(int i = 1; i < routes[0]; i += 2) if(routes[i + 1] != -1) {
for(int j = routes[i] + threadIdx.x; j < routes[i] + routes[i + 1]; j += blockDim.x)
wires[j]++;
}*/
}
/*
__global__ void cudaPatternRoute(int *map, int *points, int64_t *wireCostSum, int *viaCost, int *prev, int *wires, int
*vias, int *routes, int LAYER, int N, int DIRECTION) {
//printf("%d offset %d\n", threadIdx.x, points[threadIdx.x]);
points += points[blockIdx.x];
if(threadIdx.x == 0)
routes += points[0], routes[0] = 1;
int node_cnt = points[1];
points += 2;
for(int t = 6 * (node_cnt - 1); t >= 0; t -= 6) {
int tox = points[t] / N, toy = points[t] % N, minlayer = points[t + 1], maxlayer = points[t + 2];
for(int j = 1; j <= 3; j++) if(points[t + 2 + j] != -1) {
int fromx = points[t + 2 + j] / N, fromy = points[t + 2 + j] % N;
//printf("%d %d to %d %d\n", fromx, fromy, tox, toy);
if(fromx != tox && fromy != toy) {
{
int i = threadIdx.x;
if((i & 1) ^ DIRECTION)
map[4 * LAYER * N * N + i * N * N + fromx * N + toy] = map[4 * LAYER * N * N + i * N * N + tox *
N + fromy] = INF; else map[4 * LAYER * N * N + i * N * N + toy * N + fromx] = map[4 * LAYER * N * N + i * N * N + fromy
* N + tox] = INF;
}
__syncthreads();
if(threadIdx.x) {
int i = threadIdx.x;
int last = i * N * N + (((i & 1) ^ DIRECTION) ? fromx * N + fromy : fromy * N + fromx);
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? fromx * N + toy : fromy * N + tox);
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] - wireCostSum[last];
if(map[4 * LAYER * N * N + cur] > map[last] + cost)
map[4 * LAYER * N * N + cur] = map[last] + cost, prev[4 * LAYER * N * N + cur] = last;
}
__syncthreads();
if(threadIdx.x == 0) {
viaSweep(map, prev, viaCost, fromx, toy, LAYER, N, DIRECTION);
viaSweep(map, prev, viaCost, tox, fromy, LAYER, N, DIRECTION);
}
__syncthreads();
if(threadIdx.x) {
int i = threadIdx.x;
int last = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + fromy : toy * N + fromx);
int cur = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] - wireCostSum[last];
if(map[cur + j * LAYER * N * N] > map[4 * LAYER * N * N + last] + cost)
map[cur + j * LAYER * N * N] = map[4 * LAYER * N * N + last] + cost, prev[cur + j * LAYER * N *
N] = prev[4 * LAYER * N * N + last];
}
} else if(fromx == tox) {
if(threadIdx.x) {
int i = threadIdx.x;
if((i & 1) ^ DIRECTION) {
int last = i * N * N + fromx * N + fromy, cur = i * N * N + tox * N + toy;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] -
wireCostSum[last]; if(map[cur + j * LAYER * N * N] > map[last] + cost) map[cur + j * LAYER * N * N] = map[last] + cost,
prev[cur + j * LAYER * N * N] = last;
}
}
} else if(fromy == toy) {
if(threadIdx.x) {
int i = threadIdx.x;
if(!(i & 1) ^ DIRECTION) {
int last = i * N * N + fromy * N + fromx, cur = i * N * N + toy * N + tox;
int cost = last < cur ? wireCostSum[last] - wireCostSum[cur] : wireCostSum[cur] -
wireCostSum[last]; if(map[cur + j * LAYER * N * N] > map[last] + cost) map[cur + j * LAYER * N * N] = map[last] + cost,
prev[cur + j * LAYER * N * N] = last;
}
}
} else
printf("ERROR: points on the same location!\n");
}
__syncthreads();
if(threadIdx.x == 0) for(int lower = 0; lower < LAYER; lower++) {
int viaSum = 0, minCost = INF, bestpos[3] = {0, 0, 0}, costs[3] = {points[t + 3] == -1 ? 0 : INF, points[t +
4] == -1 ? 0 : INF, points[t + 5] == -1 ? 0 : INF}; for(int upper = lower; upper < LAYER; upper++) { int idx = upper * N
* N + (((upper & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox); for(int j = 0; j < 3; j++) if(points[t + 3 + j] !=
-1) { if(map[idx + (j + 1) * LAYER * N * N] < costs[j]) costs[j] = map[idx + (j + 1) * LAYER * N * N], bestpos[j] =
upper;
}
//if(upper == 0)
// printf("cost[0] = %d\n", costs[0]);
if(1LL * costs[0] + costs[1] + costs[2] < minCost)
minCost = costs[0] + costs[1] + costs[2];
if(minlayer == -1 || (lower <= minlayer && maxlayer <= upper)) {
//printf("upper %d viaSUm %d\n", upper, viaSum);
for(int i = lower; i <= upper; i++) {
int index = i * N * N + (((i & 1) ^ DIRECTION) ? tox * N + toy : toy * N + tox);
if(map[index] > minCost + viaSum)
map[index] = minCost + viaSum, prev[index] = (((lower * LAYER + upper) * LAYER + bestpos[2])
* LAYER + bestpos[1]) * LAYER + bestpos[0];
}
}
viaSum += viaCost[idx];
}
}
}
__syncthreads();
if(threadIdx.x) return;
int minTotalDist = INF;
for(int i = 0; i < LAYER; i++) {
int x = points[0] / N, y = points[0] % N;
int idx = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
if(map[idx] < minTotalDist)
minTotalDist = map[idx], map[4 * LAYER * N * N + points[0]] = i;
}
if(minTotalDist == INF || minTotalDist < 0) {
printf("INF is too small!\n");
return;
}
for(int t = 0; t < 6 * node_cnt; t += 6) {
int x = points[t] / N, y = points[t] % N, layer = map[4 * LAYER * N * N + points[t]];
int idx = layer * N * N + (((layer & 1) ^ DIRECTION) ? x * N + y : y * N + x);
int minlayer = prev[idx] / LAYER / LAYER / LAYER / LAYER, maxlayer = prev[idx] / LAYER / LAYER / LAYER % LAYER;
//printf("%d [%d, %d] exit/min/max layer\n", layer, minlayer, maxlayer);
for(int i = minlayer; i < maxlayer; i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? x * N + y : y * N + x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
int bestpos = prev[idx];
for(int j = 0; j < 3; j++) {
int child = points[t + 3 + j];
if(points[t + 3 + j] == -1) break;
int entrylayer = bestpos % LAYER, entry = entrylayer * N * N + (((entrylayer & 1) ^ DIRECTION) ? x * N + y :
y * N + x);
//printf("(%d, %d, %d) ", entrylayer, x, y);
bestpos /= LAYER;
int last = prev[(j + 1) * LAYER * N * N + entry];
int lastlayer = last / N / N, lastx = last / N % N, lasty = last % N;
if(!(lastlayer & 1) ^ DIRECTION) cudaSwap(lastx, lasty);
if(lastx != x && lasty != y) {
int _x = ((entrylayer & 1) ^ DIRECTION) ? x : lastx;
int _y = ((entrylayer & 1) ^ DIRECTION) ? lasty : y;
int p1 = ((entrylayer & 1) ^ DIRECTION) ? entry - y + lasty : entry - x + lastx;
int p2 = ((lastlayer & 1) ^ DIRECTION) ? last - lasty + y : last - lastx + x;
routes[routes[0]++] = min(entry, p1);
routes[routes[0]++] = max(entry, p1) - min(entry, p1);
for(int i = min(entry, p1); i < max(entry, p1); i++)
atomicAdd(wires + i, 1);
routes[routes[0]++] = min(last, p2);
routes[routes[0]++] = max(last, p2) - min(last, p2);
for(int i = min(last, p2); i < max(last, p2); i++)
atomicAdd(wires + i, 1);
for(int i = min(lastlayer, entrylayer); i < max(lastlayer, entrylayer); i++) {
int id = i * N * N + (((i & 1) ^ DIRECTION) ? _x * N + _y : _y * N + _x);
routes[routes[0]++] = id;
routes[routes[0]++] = -1;
atomicAdd(vias + id, 1);
}
} else {
routes[routes[0]++] = min(last, entry);
routes[routes[0]++] = max(last, entry) - min(last, entry);
for(int i = min(last, entry); i < max(last, entry); i++)
atomicAdd(wires + i, 1);
}
//if(x == 46 && y == 47)
// printf("(%d %d %d) <- (%d %d %d)\n", entrylayer, entry / N % N, entry % N, last / N / N, last / N % N,
last % N); map[4 * LAYER * N * N + child] = lastlayer;
}
}
if(debug) for(int i = 1; i < routes[0]; i += 2) {
int layer = routes[i] / N / N, x = routes[i] / N % N, y = routes[i] % N;
if((layer & 1) ^ DIRECTION) {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer + 1, x, y);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, x, y, layer, x, y + routes[i + 1]);
} else {
if(routes[i + 1] == -1)
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer + 1, y, x);
else
printf("{%d, %d, %d}, {%d, %d, %d}, ", layer, y, x, layer, y + routes[i + 1], x);
}
}
}*/
__global__ void preprocess(int *wires, int *vias) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
wires[index] <<= 1;
vias[index] <<= 1;
}
__global__ void postprocess(int *wires, int *vias) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
wires[index] = wires[index] / 2 + wires[index] % 2;
vias[index] = vias[index] / 2 + vias[index] % 2;
}
__global__ void cudaWrite(int *wires, int *vias, int N, int LAYER) {
for (int i = 0; i < LAYER; i++)
for (int j = 0; j < N; j++)
for (int k = 0; k < N; k++) printf("%d\n", vias[i * N * N + j * N + k]);
}
void patternRoute(int *points,
int batchSize,
int64_t *wireCostSum,
int *viaCost,
int *map,
int *prev,
int *wires,
int *vias,
int *routes,
int *gbpoints,
int *gbpinRoutes,
int X,
int Y,
int N,
int LAYER,
int DIRECTION) {
// debug = 1;
initMap<<<6 * LAYER * N * 2, N / 2>>>(map);
// cudaDeviceSynchronize();
// static int cnt = 11395;
// cudaLshapePR<<<batchSize, 1>>> (map, points, wireCostSum, viaCost, prev, wires, vias, routes, LAYER, N,
// DIRECTION);
// for (int i = 0; i < batchSize; i++) {
// cudaPatternRouteParallel<<<1, 32>>>(
// map, points + points[i], wireCostSum, viaCost, prev, prev + 10 * LAYER * N * N,
// wires, vias, routes, gbpoints + gbpoints[i], gbpinRoutes, LAYER, N, DIRECTION);
// }
cudaPatternRouteParallel<<<batchSize, 32>>>(
map, points, wireCostSum, viaCost, prev, prev + 10 * LAYER * N * N,
wires, vias, routes, gbpoints, gbpinRoutes, LAYER, N, DIRECTION);
// cudaPatternRoute<<<batchSize, LAYER>>> (map, points, wireCostSum, viaCost, prev, wires, vias, routes, LAYER, N,
// DIRECTION);
{
cudaDeviceSynchronize();
int errorType = cudaGetLastError();
if (errorType) {
std::cerr << "PR1 CUDA ERROR: " << errorType << std::endl;
exit(0);
}
}
// exit(0);
// if(--cnt == 0) exit(0);
}
} // namespace gr