PageRenderTime 71ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/src/plugins/select/bluegene/ba/block_allocator.c

https://github.com/cfenoy/slurm
C | 3372 lines | 2555 code | 329 blank | 488 comment | 608 complexity | 6c61c1ad98648645d8aa3896e78e8425 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * block_allocator.c - Assorted functions for layout of bluegene blocks,
  3. * wiring, mapping for smap, etc.
  4. * $Id$
  5. *****************************************************************************
  6. * Copyright (C) 2004-2007 The Regents of the University of California.
  7. * Copyright (C) 2008-2009 Lawrence Livermore National Security.
  8. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  9. * Written by Dan Phung <phung4@llnl.gov>, Danny Auble <da@llnl.gov>
  10. *
  11. * This file is part of SLURM, a resource management program.
  12. * For details, see <http://www.schedmd.com/slurmdocs/>.
  13. * Please also read the included file: DISCLAIMER.
  14. *
  15. * SLURM is free software; you can redistribute it and/or modify it under
  16. * the terms of the GNU General Public License as published by the Free
  17. * Software Foundation; either version 2 of the License, or (at your option)
  18. * any later version.
  19. *
  20. * In addition, as a special exception, the copyright holders give permission
  21. * to link the code of portions of this program with the OpenSSL library under
  22. * certain conditions as described in each individual source file, and
  23. * distribute linked combinations including the two. You must obey the GNU
  24. * General Public License in all respects for all of the code used other than
  25. * OpenSSL. If you modify file(s) with this exception, you may extend this
  26. * exception to your version of the file(s), but you are not obligated to do
  27. * so. If you do not wish to do so, delete this exception statement from your
  28. * version. If you delete this exception statement from all source files in
  29. * the program, then also delete it here.
  30. *
  31. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  32. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  33. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  34. * details.
  35. *
  36. * You should have received a copy of the GNU General Public License along
  37. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  38. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  39. \*****************************************************************************/
  40. #if HAVE_CONFIG_H
  41. # include "config.h"
  42. #endif
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <math.h>
  46. #include "block_allocator.h"
  47. #include "src/common/slurmdb_defs.h"
  48. #include "src/common/timers.h"
  49. #include "src/common/uid.h"
  50. /*
  51. * structure that holds switch path information for finding the wiring
  52. * path without setting the configuration.
  53. *
  54. * - dim - Which Axis it is on
  55. * - geometry - node location
  56. * - in - ingress port.
  57. * - out - egress port.
  58. *
  59. */
  60. typedef struct {
  61. int dim;
  62. uint16_t geometry[HIGHEST_DIMENSIONS];
  63. int in;
  64. int out;
  65. } ba_path_switch_t;
  66. #define DEBUG_PA
  67. #define BEST_COUNT_INIT 20
  68. /* Global */
  69. bool _initialized = false;
  70. bool _wires_initialized = false;
  71. bool _mp_map_initialized = false;
  72. /* _ba_system is the "current" system that the structures will work
  73. * on */
  74. List path = NULL;
  75. List best_path = NULL;
  76. int best_count;
  77. uint16_t *deny_pass = NULL;
  78. char *p = '\0';
  79. /* extern Global */
  80. my_bluegene_t *bg = NULL;
  81. ba_mp_t ***ba_main_grid = NULL;
  82. typedef enum {
  83. BLOCK_ALGO_FIRST,
  84. BLOCK_ALGO_SECOND
  85. } block_algo_t;
  86. /** internal helper functions */
  87. /* */
  88. static int _check_for_options(select_ba_request_t* ba_request);
  89. /* */
  90. static int _append_geo(uint16_t *geo, List geos, int rotate);
  91. /* */
  92. static int _fill_in_coords(List results, List start_list,
  93. uint16_t *geometry, int conn_type);
  94. /* */
  95. static int _copy_the_path(List nodes, ba_switch_t *curr_switch,
  96. ba_switch_t *mark_switch,
  97. int source, int dim);
  98. /* */
  99. static int _find_yz_path(ba_mp_t *ba_node, uint16_t *first,
  100. uint16_t *geometry, int conn_type);
  101. #ifndef HAVE_BG_FILES
  102. /* */
  103. static int _emulate_ext_wiring(ba_mp_t ***grid);
  104. #endif
  105. /** */
  106. static int _reset_the_path(ba_switch_t *curr_switch, int source,
  107. int target, int dim);
  108. /* */
  109. static void _delete_path_list(void *object);
  110. /* find the first block match in the system */
  111. static int _find_match(select_ba_request_t* ba_request, List results);
  112. /** */
  113. static bool _node_used(ba_mp_t* ba_node, int x_size);
  114. /* */
  115. static void _switch_config(ba_mp_t* source, ba_mp_t* target, int dim,
  116. int port_src, int port_tar);
  117. /* */
  118. static int _set_external_wires(int dim, int count, ba_mp_t* source,
  119. ba_mp_t* target);
  120. /* */
  121. static char *_set_internal_wires(List nodes, int size, int conn_type);
  122. /* */
  123. static int _find_x_path(List results, ba_mp_t *ba_node, uint16_t *start,
  124. int x_size, int found, int conn_type,
  125. block_algo_t algo);
  126. /* */
  127. static int _remove_node(List results, uint16_t *mp_tar);
  128. /* */
  129. static int _find_next_free_using_port_2(ba_switch_t *curr_switch,
  130. int source_port,
  131. List nodes, int dim,
  132. int count);
  133. /* */
  134. /* static int _find_passthrough(ba_switch_t *curr_switch, int source_port, */
  135. /* List nodes, int dim, */
  136. /* int count, int highest_phys_x); */
  137. /* */
  138. static int _finish_torus(List results,
  139. ba_switch_t *curr_switch, int source_port,
  140. int dim, int count, uint16_t *start);
  141. /* */
  142. static uint16_t *_set_best_path();
  143. /* */
  144. static int _set_one_dim(uint16_t *start, uint16_t *end, uint16_t *coord);
  145. /* */
  146. static void _destroy_geo(void *object);
  147. extern void destroy_ba_node(void *ptr)
  148. {
  149. ba_mp_t *ba_node = (ba_mp_t *)ptr;
  150. if (ba_node) {
  151. xfree(ba_node->loc);
  152. xfree(ba_node);
  153. }
  154. }
  155. /*
  156. * create a block request. Note that if the geometry is given,
  157. * then size is ignored. If elongate is true, the algorithm will try
  158. * to fit that a block of cubic shape and then it will try other
  159. * elongated geometries. (ie, 2x2x2 -> 4x2x1 -> 8x1x1).
  160. *
  161. * IN/OUT - ba_request: structure to allocate and fill in.
  162. *
  163. * ALL below IN's need to be set within the ba_request before the call
  164. * if you want them to be used.
  165. * ALL below OUT's are set and returned within the ba_request.
  166. * IN - avail_node_bitmap: bitmap of usable midplanes.
  167. * IN - blrtsimage: BlrtsImage for this block if not default
  168. * IN - conn_type: connection type of request (TORUS or MESH or SMALL)
  169. * IN - elongate: if true, will try to fit different geometries of
  170. * same size requests
  171. * IN/OUT - geometry: requested/returned geometry of block
  172. * IN - linuximage: LinuxImage for this block if not default
  173. * IN - mloaderimage: MLoaderImage for this block if not default
  174. * IN - nodecards: Number of nodecards in each block in request only
  175. * used of small block allocations.
  176. * OUT - passthroughs: if there were passthroughs used in the
  177. * generation of the block.
  178. * IN - procs: Number of real processors requested
  179. * IN - quarters: Number of midplane quarters in each block in request only
  180. * used of small block allocations.
  181. * IN - RamDiskimage: RamDiskImage for this block if not default
  182. * IN - rotate: if true, allows rotation of block during fit
  183. * OUT - save_name: hostlist of midplanes used in block
  184. * IN/OUT - size: requested/returned count of midplanes in block
  185. * IN - start: geo location of where to start the allocation
  186. * IN - start_req: if set use the start variable to start at
  187. * return success of allocation/validation of params
  188. */
  189. extern int new_ba_request(select_ba_request_t* ba_request)
  190. {
  191. int i=0;
  192. float sz=1;
  193. int i2, picked, total_sz=1, size2=0;
  194. uint16_t *geo_ptr;
  195. int messed_with = 0;
  196. int checked[DIM_SIZE[X]];
  197. uint16_t geo[cluster_dims];
  198. memset(geo, 0, sizeof(geo));
  199. ba_request->save_name= NULL;
  200. ba_request->rotate_count= 0;
  201. ba_request->elongate_count = 0;
  202. ba_request->elongate_geos = list_create(_destroy_geo);
  203. memcpy(geo, ba_request->geometry, sizeof(geo));
  204. if (ba_request->deny_pass == (uint16_t)NO_VAL)
  205. ba_request->deny_pass = ba_deny_pass;
  206. if (!(cluster_flags & CLUSTER_FLAG_BG)) {
  207. if (geo[X] != (uint16_t)NO_VAL) {
  208. for (i=0; i<cluster_dims; i++) {
  209. if ((geo[i] < 1) || (geo[i] > DIM_SIZE[i])) {
  210. error("new_ba_request Error, "
  211. "request geometry is invalid %d",
  212. geo[i]);
  213. return 0;
  214. }
  215. }
  216. ba_request->size = ba_request->geometry[X];
  217. } else if (ba_request->size) {
  218. ba_request->geometry[X] = ba_request->size;
  219. } else
  220. return 0;
  221. return 1;
  222. }
  223. if (geo[X] != (uint16_t)NO_VAL) {
  224. for (i=0; i<cluster_dims; i++){
  225. if ((geo[i] < 1) || (geo[i] > DIM_SIZE[i])) {
  226. error("new_ba_request Error, "
  227. "request geometry is invalid dim %d "
  228. "can't be %c, largest is %c",
  229. i,
  230. alpha_num[geo[i]],
  231. alpha_num[DIM_SIZE[i]]);
  232. return 0;
  233. }
  234. }
  235. _append_geo(geo, ba_request->elongate_geos, 0);
  236. sz=1;
  237. for (i=0; i<cluster_dims; i++)
  238. sz *= ba_request->geometry[i];
  239. ba_request->size = sz;
  240. sz=0;
  241. }
  242. deny_pass = &ba_request->deny_pass;
  243. if (ba_request->elongate || sz) {
  244. sz=1;
  245. /* decompose the size into a cubic geometry */
  246. ba_request->rotate= 1;
  247. ba_request->elongate = 1;
  248. for (i=0; i<cluster_dims; i++) {
  249. total_sz *= DIM_SIZE[i];
  250. geo[i] = 1;
  251. }
  252. if (ba_request->size==1) {
  253. _append_geo(geo,
  254. ba_request->elongate_geos,
  255. ba_request->rotate);
  256. goto endit;
  257. }
  258. if (ba_request->size<=DIM_SIZE[Y]) {
  259. geo[X] = 1;
  260. geo[Y] = ba_request->size;
  261. geo[Z] = 1;
  262. sz=ba_request->size;
  263. _append_geo(geo,
  264. ba_request->elongate_geos,
  265. ba_request->rotate);
  266. }
  267. i = ba_request->size/4;
  268. if (!(ba_request->size%2)
  269. && i <= DIM_SIZE[Y]
  270. && i <= DIM_SIZE[Z]
  271. && i*i == ba_request->size) {
  272. geo[X] = 1;
  273. geo[Y] = i;
  274. geo[Z] = i;
  275. sz=ba_request->size;
  276. _append_geo(geo,
  277. ba_request->elongate_geos,
  278. ba_request->rotate);
  279. }
  280. if (ba_request->size > total_sz || ba_request->size < 1) {
  281. return 0;
  282. }
  283. sz = ba_request->size % (DIM_SIZE[Y] * DIM_SIZE[Z]);
  284. if (!sz) {
  285. i = ba_request->size / (DIM_SIZE[Y] * DIM_SIZE[Z]);
  286. geo[X] = i;
  287. geo[Y] = DIM_SIZE[Y];
  288. geo[Z] = DIM_SIZE[Z];
  289. sz=ba_request->size;
  290. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  291. _append_geo(geo,
  292. ba_request->elongate_geos,
  293. ba_request->rotate);
  294. else
  295. error("%d I was just trying to add a "
  296. "geo of %d%d%d "
  297. "while I am trying to request "
  298. "%d midplanes",
  299. __LINE__, geo[X], geo[Y], geo[Z],
  300. ba_request->size);
  301. }
  302. // startagain:
  303. picked=0;
  304. for(i=0; i<DIM_SIZE[X]; i++)
  305. checked[i]=0;
  306. for (i=0; i<cluster_dims; i++) {
  307. total_sz *= DIM_SIZE[i];
  308. geo[i] = 1;
  309. }
  310. sz = 1;
  311. picked=0;
  312. tryagain:
  313. size2 = ba_request->size;
  314. //messedup:
  315. for (i=picked; i<cluster_dims; i++) {
  316. if (size2 <= 1)
  317. break;
  318. sz = size2 % DIM_SIZE[i];
  319. if (!sz) {
  320. geo[i] = DIM_SIZE[i];
  321. size2 /= DIM_SIZE[i];
  322. } else if (size2 > DIM_SIZE[i]) {
  323. for(i2=(DIM_SIZE[i]-1); i2 > 1; i2--) {
  324. /* go through each number to see if
  325. the size is divisable by a smaller
  326. number that is
  327. good in the other dims. */
  328. if (!(size2%i2) && !checked[i2]) {
  329. size2 /= i2;
  330. if (i==0)
  331. checked[i2]=1;
  332. if (i2<DIM_SIZE[i]) {
  333. geo[i] = i2;
  334. } else {
  335. goto tryagain;
  336. }
  337. if ((i2-1)!=1 &&
  338. i!=(cluster_dims-1))
  339. break;
  340. }
  341. }
  342. /* This size can not be made into a
  343. block return. If you want to try
  344. until we find the next largest block
  345. uncomment the code below and the goto
  346. above. If a user specifies a max
  347. node count the job will never
  348. run.
  349. */
  350. if (i2==1) {
  351. if (!list_count(
  352. ba_request->elongate_geos))
  353. error("Can't make a block of "
  354. "%d into a cube.",
  355. ba_request->size);
  356. goto endit;
  357. /* ba_request->size +=1; */
  358. /* goto startagain; */
  359. }
  360. } else {
  361. geo[i] = sz;
  362. break;
  363. }
  364. }
  365. if ((geo[X]*geo[Y]) <= DIM_SIZE[Y]) {
  366. ba_request->geometry[X] = 1;
  367. ba_request->geometry[Y] = geo[X] * geo[Y];
  368. ba_request->geometry[Z] = geo[Z];
  369. _append_geo(ba_request->geometry,
  370. ba_request->elongate_geos,
  371. ba_request->rotate);
  372. }
  373. if ((geo[X]*geo[Z]) <= DIM_SIZE[Y]) {
  374. ba_request->geometry[X] = 1;
  375. ba_request->geometry[Y] = geo[Y];
  376. ba_request->geometry[Z] = geo[X] * geo[Z];
  377. _append_geo(ba_request->geometry,
  378. ba_request->elongate_geos,
  379. ba_request->rotate);
  380. }
  381. /* Make sure geo[X] is even and then see if we can get
  382. it into the Y or Z dim. */
  383. if (!(geo[X]%2) && ((geo[X]/2) <= DIM_SIZE[Y])) {
  384. if (geo[Y] == 1) {
  385. ba_request->geometry[Y] = geo[X]/2;
  386. messed_with = 1;
  387. } else
  388. ba_request->geometry[Y] = geo[Y];
  389. if (!messed_with && geo[Z] == 1) {
  390. messed_with = 1;
  391. ba_request->geometry[Z] = geo[X]/2;
  392. } else
  393. ba_request->geometry[Z] = geo[Z];
  394. if (messed_with) {
  395. messed_with = 0;
  396. ba_request->geometry[X] = 2;
  397. _append_geo(ba_request->geometry,
  398. ba_request->elongate_geos,
  399. ba_request->rotate);
  400. }
  401. }
  402. if (geo[X] == DIM_SIZE[X]
  403. && (geo[Y] < DIM_SIZE[Y]
  404. || geo[Z] < DIM_SIZE[Z])) {
  405. if (DIM_SIZE[Y]<DIM_SIZE[Z]) {
  406. i = DIM_SIZE[Y];
  407. DIM_SIZE[Y] = DIM_SIZE[Z];
  408. DIM_SIZE[Z] = i;
  409. }
  410. ba_request->geometry[X] = geo[X];
  411. ba_request->geometry[Y] = geo[Y];
  412. ba_request->geometry[Z] = geo[Z];
  413. if (ba_request->geometry[Y] < DIM_SIZE[Y]) {
  414. i = (DIM_SIZE[Y] - ba_request->geometry[Y]);
  415. ba_request->geometry[Y] +=i;
  416. }
  417. if (ba_request->geometry[Z] < DIM_SIZE[Z]) {
  418. i = (DIM_SIZE[Z] - ba_request->geometry[Z]);
  419. ba_request->geometry[Z] +=i;
  420. }
  421. for(i = DIM_SIZE[X]; i>0; i--) {
  422. ba_request->geometry[X]--;
  423. i2 = (ba_request->geometry[X]
  424. * ba_request->geometry[Y]
  425. * ba_request->geometry[Z]);
  426. if (i2 < ba_request->size) {
  427. ba_request->geometry[X]++;
  428. messed_with = 1;
  429. break;
  430. }
  431. }
  432. if (messed_with) {
  433. messed_with = 0;
  434. _append_geo(ba_request->geometry,
  435. ba_request->elongate_geos,
  436. ba_request->rotate);
  437. }
  438. }
  439. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  440. _append_geo(geo,
  441. ba_request->elongate_geos,
  442. ba_request->rotate);
  443. else
  444. error("%d I was just trying to add a geo of %d%d%d "
  445. "while I am trying to request %d midplanes",
  446. __LINE__, geo[X], geo[Y], geo[Z],
  447. ba_request->size);
  448. /* Having the functions pow and powf on an aix system doesn't seem to
  449. * link well, so since this is only for aix and this doesn't really
  450. * need to be there just don't allow this extra calculation.
  451. */
  452. #ifndef HAVE_AIX
  453. /* see if We can find a cube or square root of the
  454. size to make an easy cube */
  455. for(i=0; i<cluster_dims-1; i++) {
  456. sz = powf((float)ba_request->size,
  457. (float)1/(cluster_dims-i));
  458. if (pow(sz,(cluster_dims-i)) == ba_request->size)
  459. break;
  460. }
  461. if (i < (cluster_dims-1)) {
  462. /* we found something that looks like a cube! */
  463. int i3 = i;
  464. for (i=0; i<i3; i++)
  465. geo[i] = 1;
  466. for (i=i3; i<cluster_dims; i++)
  467. if (sz<=DIM_SIZE[i])
  468. geo[i] = sz;
  469. else
  470. goto endit;
  471. if ((geo[X]*geo[Y]*geo[Z]) == ba_request->size)
  472. _append_geo(geo,
  473. ba_request->elongate_geos,
  474. ba_request->rotate);
  475. else
  476. error("%d I was just trying to add "
  477. "a geo of %d%d%d "
  478. "while I am trying to request "
  479. "%d midplanes",
  480. __LINE__, geo[X], geo[Y], geo[Z],
  481. ba_request->size);
  482. }
  483. #endif //HAVE_AIX
  484. }
  485. endit:
  486. if (!(geo_ptr = list_peek(ba_request->elongate_geos)))
  487. return 0;
  488. ba_request->elongate_count++;
  489. ba_request->geometry[X] = geo_ptr[X];
  490. ba_request->geometry[Y] = geo_ptr[Y];
  491. ba_request->geometry[Z] = geo_ptr[Z];
  492. sz=1;
  493. for (i=0; i<cluster_dims; i++)
  494. sz *= ba_request->geometry[i];
  495. ba_request->size = sz;
  496. return 1;
  497. }
  498. /**
  499. * print a block request
  500. */
  501. extern void print_ba_request(select_ba_request_t* ba_request)
  502. {
  503. int i;
  504. if (ba_request == NULL){
  505. error("print_ba_request Error, request is NULL");
  506. return;
  507. }
  508. debug(" ba_request:");
  509. debug(" geometry:\t");
  510. for (i=0; i<cluster_dims; i++){
  511. debug("%d", ba_request->geometry[i]);
  512. }
  513. debug(" size:\t%d", ba_request->size);
  514. debug(" conn_type:\t%d", ba_request->conn_type[X]);
  515. debug(" rotate:\t%d", ba_request->rotate);
  516. debug(" elongate:\t%d", ba_request->elongate);
  517. }
  518. /* If emulating a system set up a known configuration for wires in a
  519. * system of the size given.
  520. * If a real bluegene system, query the system and get all wiring
  521. * information of the system.
  522. */
  523. extern void init_wires(void)
  524. {
  525. int x, y, z, i;
  526. ba_mp_t *source = NULL;
  527. if (_wires_initialized)
  528. return;
  529. for(x=0;x<DIM_SIZE[X];x++) {
  530. for(y=0;y<DIM_SIZE[Y];y++) {
  531. for(z=0;z<DIM_SIZE[Z];z++) {
  532. source = &ba_main_grid[x][y][z];
  533. for(i=0; i<NUM_PORTS_PER_NODE; i++) {
  534. _switch_config(source, source,
  535. X, i, i);
  536. _switch_config(source, source,
  537. Y, i, i);
  538. _switch_config(source, source,
  539. Z, i, i);
  540. }
  541. }
  542. }
  543. }
  544. #ifdef HAVE_BG_FILES
  545. _set_external_wires(0,0,NULL,NULL);
  546. if (bridge_setup_system() == -1)
  547. return;
  548. #endif
  549. _wires_initialized = true;
  550. return;
  551. }
  552. /*
  553. * copy the path of the nodes given
  554. *
  555. * IN nodes List of ba_mp_t *'s: nodes to be copied
  556. * OUT dest_nodes List of ba_mp_t *'s: filled in list of nodes
  557. * wiring.
  558. * Return on success SLURM_SUCCESS, on error SLURM_ERROR
  559. */
  560. extern int copy_node_path(List nodes, List *dest_nodes)
  561. {
  562. int rc = SLURM_ERROR;
  563. #ifdef HAVE_BG_L_P
  564. ListIterator itr = NULL;
  565. ListIterator itr2 = NULL;
  566. ba_mp_t *ba_node = NULL, *new_ba_node = NULL;
  567. int dim;
  568. ba_switch_t *curr_switch = NULL, *new_switch = NULL;
  569. if (!nodes)
  570. return SLURM_ERROR;
  571. if (!*dest_nodes)
  572. *dest_nodes = list_create(destroy_ba_node);
  573. itr = list_iterator_create(nodes);
  574. while ((ba_node = list_next(itr))) {
  575. itr2 = list_iterator_create(*dest_nodes);
  576. while ((new_ba_node = list_next(itr2))) {
  577. if (ba_node->coord[X] == new_ba_node->coord[X] &&
  578. ba_node->coord[Y] == new_ba_node->coord[Y] &&
  579. ba_node->coord[Z] == new_ba_node->coord[Z])
  580. break; /* we found it */
  581. }
  582. list_iterator_destroy(itr2);
  583. if (!new_ba_node) {
  584. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  585. info("adding %c%c%c as a new node",
  586. alpha_num[ba_node->coord[X]],
  587. alpha_num[ba_node->coord[Y]],
  588. alpha_num[ba_node->coord[Z]]);
  589. new_ba_node = ba_copy_mp(ba_node);
  590. ba_setup_mp(new_ba_node, false, false);
  591. list_push(*dest_nodes, new_ba_node);
  592. }
  593. new_ba_node->used = true;
  594. for(dim=0;dim<cluster_dims;dim++) {
  595. curr_switch = &ba_node->axis_switch[dim];
  596. new_switch = &new_ba_node->axis_switch[dim];
  597. if (curr_switch->int_wire[0].used) {
  598. if (!_copy_the_path(*dest_nodes,
  599. curr_switch, new_switch,
  600. 0, dim)) {
  601. rc = SLURM_ERROR;
  602. break;
  603. }
  604. }
  605. }
  606. }
  607. list_iterator_destroy(itr);
  608. rc = SLURM_SUCCESS;
  609. #endif
  610. return rc;
  611. }
  612. extern ba_mp_t *coord2ba_mp(const uint16_t *coord)
  613. {
  614. if ((coord[X] >= DIM_SIZE[X]) || (coord[Y] >= DIM_SIZE[Y]) ||
  615. (coord[Z] >= DIM_SIZE[Z])) {
  616. error("Invalid coordinate %d:%d:%d",
  617. coord[X], coord[Y], coord[Z]);
  618. return NULL;
  619. }
  620. return &ba_main_grid[coord[X]][coord[Y]][coord[Z]];
  621. }
  622. /*
  623. * Try to allocate a block.
  624. *
  625. * IN - ba_request: allocation request
  626. * OUT - results: List of results of the allocation request. Each
  627. * list entry will be a coordinate. allocate_block will create the
  628. * list, but the caller must destroy it.
  629. *
  630. * return: success or error of request
  631. */
  632. extern int allocate_block(select_ba_request_t* ba_request, List results)
  633. {
  634. if (!ba_initialized){
  635. error("Error, configuration not initialized, "
  636. "calling ba_init(NULL, 1)");
  637. ba_init(NULL, 1);
  638. }
  639. if (!ba_request){
  640. error("allocate_block Error, request not initialized");
  641. return 0;
  642. }
  643. // _backup_ba_system();
  644. if (_find_match(ba_request, results)){
  645. return 1;
  646. } else {
  647. return 0;
  648. }
  649. }
  650. /*
  651. * Admin wants to remove a previous allocation.
  652. * will allow Admin to delete a previous allocation retrival by letter code.
  653. */
  654. extern int remove_block(List nodes, bool is_small)
  655. {
  656. int dim;
  657. ba_mp_t* curr_ba_node = NULL;
  658. ba_mp_t* ba_node = NULL;
  659. ba_switch_t *curr_switch = NULL;
  660. ListIterator itr;
  661. itr = list_iterator_create(nodes);
  662. while ((curr_ba_node = (ba_mp_t*) list_next(itr))) {
  663. /* since the list that comes in might not be pointers
  664. to the main list we need to point to that main list */
  665. ba_node = &ba_main_grid[curr_ba_node->coord[X]]
  666. [curr_ba_node->coord[Y]]
  667. [curr_ba_node->coord[Z]];
  668. if (curr_ba_node->used)
  669. ba_node->used &= (~BA_MP_USED_TRUE);
  670. /* Small blocks don't use wires, and only have 1 node,
  671. so just break. */
  672. if (is_small)
  673. break;
  674. for(dim=0;dim<cluster_dims;dim++) {
  675. curr_switch = &ba_node->axis_switch[dim];
  676. if (curr_switch->int_wire[0].used) {
  677. _reset_the_path(curr_switch, 0, 1, dim);
  678. }
  679. }
  680. }
  681. list_iterator_destroy(itr);
  682. return 1;
  683. }
  684. /*
  685. * Used to set a block into a virtual system. The system can be
  686. * cleared first and this function sets all the wires and midplanes
  687. * used in the nodelist given. The nodelist is a list of ba_mp_t's
  688. * that are already set up. This is very handly to test if there are
  689. * any passthroughs used by one block when adding another block that
  690. * also uses those wires, and neither use any overlapping
  691. * midplanes. Doing a simple bitmap & will not reveal this.
  692. *
  693. * Returns SLURM_SUCCESS if nodelist fits into system without
  694. * conflict, and SLURM_ERROR if nodelist conflicts with something
  695. * already in the system.
  696. */
  697. extern int check_and_set_mp_list(List nodes)
  698. {
  699. int rc = SLURM_ERROR;
  700. #ifdef HAVE_BG_L_P
  701. int i, j;
  702. ba_switch_t *ba_switch = NULL, *curr_ba_switch = NULL;
  703. ba_mp_t *ba_node = NULL, *curr_ba_node = NULL;
  704. ListIterator itr = NULL;
  705. if (!nodes)
  706. return rc;
  707. itr = list_iterator_create(nodes);
  708. while ((ba_node = list_next(itr))) {
  709. /* info("checking %c%c%c", */
  710. /* ba_node->coord[X], */
  711. /* ba_node->coord[Y], */
  712. /* ba_node->coord[Z]); */
  713. curr_ba_node = &ba_main_grid[ba_node->coord[X]]
  714. [ba_node->coord[Y]]
  715. [ba_node->coord[Z]];
  716. if (ba_node->used && curr_ba_node->used) {
  717. /* Only error if the midplane isn't already
  718. * marked down or in a error state outside of
  719. * the bluegene block.
  720. */
  721. uint16_t base_state, node_flags;
  722. base_state = curr_ba_node->state & NODE_STATE_BASE;
  723. node_flags = curr_ba_node->state & NODE_STATE_FLAGS;
  724. if (!(node_flags & (NODE_STATE_DRAIN | NODE_STATE_FAIL))
  725. && (base_state != NODE_STATE_DOWN)) {
  726. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  727. info("I have already been to "
  728. "this node %c%c%c %s",
  729. alpha_num[ba_node->coord[X]],
  730. alpha_num[ba_node->coord[Y]],
  731. alpha_num[ba_node->coord[Z]],
  732. node_state_string(
  733. curr_ba_node->state));
  734. rc = SLURM_ERROR;
  735. goto end_it;
  736. }
  737. }
  738. if (ba_node->used)
  739. curr_ba_node->used = ba_node->used;
  740. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  741. info("check_and_set_mp_list: "
  742. "%s is used ?= %d %d",
  743. curr_ba_node->coord_str,
  744. curr_ba_node->used, ba_node->used);
  745. for(i=0; i<cluster_dims; i++) {
  746. ba_switch = &ba_node->axis_switch[i];
  747. curr_ba_switch = &curr_ba_node->axis_switch[i];
  748. //info("checking dim %d", i);
  749. for(j=0; j<NUM_PORTS_PER_NODE; j++) {
  750. //info("checking port %d", j);
  751. if (ba_switch->int_wire[j].used
  752. && curr_ba_switch->int_wire[j].used
  753. && j != curr_ba_switch->
  754. int_wire[j].port_tar) {
  755. if (ba_debug_flags
  756. & DEBUG_FLAG_BG_ALGO_DEEP)
  757. info("%c%c%c dim %d port %d "
  758. "is already in use to %d",
  759. alpha_num[ba_node->
  760. coord[X]],
  761. alpha_num[ba_node->
  762. coord[Y]],
  763. alpha_num[ba_node->
  764. coord[Z]],
  765. i,
  766. j,
  767. curr_ba_switch->
  768. int_wire[j].port_tar);
  769. rc = SLURM_ERROR;
  770. goto end_it;
  771. }
  772. if (!ba_switch->int_wire[j].used)
  773. continue;
  774. /* info("setting %c%c%c dim %d port %d -> %d",*/
  775. /* alpha_num[ba_node->coord[X]], */
  776. /* alpha_num[ba_node->coord[Y]], */
  777. /* alpha_num[ba_node->coord[Z]], */
  778. /* i, */
  779. /* j, */
  780. /* ba_switch->int_wire[j].port_tar); */
  781. curr_ba_switch->int_wire[j].used = 1;
  782. curr_ba_switch->int_wire[j].port_tar
  783. = ba_switch->int_wire[j].port_tar;
  784. }
  785. }
  786. }
  787. rc = SLURM_SUCCESS;
  788. end_it:
  789. list_iterator_destroy(itr);
  790. #endif
  791. return rc;
  792. }
  793. /*
  794. * Used to find, and set up midplanes and the wires in the virtual
  795. * system and return them in List results
  796. *
  797. * IN/OUT results - a list with a NULL destroyer filled in with
  798. * midplanes and wires set to create the block with the api. If
  799. * only interested in the hostlist NULL can be excepted also.
  800. * IN ba_request - request for the block
  801. *
  802. * To be set in the ba_request
  803. * start - where to start the allocation. (optional)
  804. * geometry or size - the requested geometry of the block. (required)
  805. * conn_type - mesh, torus, or small. (required)
  806. *
  807. * RET char * - hostlist of midplanes results represent must be
  808. * xfreed. NULL on failure
  809. */
  810. extern char *set_bg_block(List results, select_ba_request_t* ba_request)
  811. {
  812. char *name = NULL;
  813. ba_mp_t* ba_node = NULL;
  814. int send_results = 0;
  815. int found = 0;
  816. xassert(ba_request);
  817. if (cluster_dims == 1) {
  818. if (ba_request->start[X]>=DIM_SIZE[X])
  819. return NULL;
  820. ba_request->size = ba_request->geometry[X];
  821. ba_node = &ba_main_grid[ba_request->start[X]][0][0];
  822. } else {
  823. int dim;
  824. ba_request->size = 1;
  825. for (dim=0; dim<cluster_dims; dim++) {
  826. if (ba_request->start[dim] >= DIM_SIZE[dim])
  827. return NULL;
  828. if ((int16_t)ba_request->geometry[dim] <= 0) {
  829. error("problem with geometry of %c in dim %d, "
  830. "needs to be at least 1",
  831. alpha_num[ba_request->geometry[dim]],
  832. dim);
  833. return NULL;
  834. }
  835. ba_request->size *= ba_request->geometry[dim];
  836. }
  837. ba_node = coord2ba_mp(ba_request->start);
  838. }
  839. if (!ba_node)
  840. return NULL;
  841. if (!results)
  842. results = list_create(NULL);
  843. else
  844. send_results = 1;
  845. /* This midplane should have already been checked if it was in
  846. use or not */
  847. list_append(results, ba_node);
  848. if (ba_request->conn_type[0] >= SELECT_SMALL) {
  849. /* adding the ba_node and ending */
  850. ba_node->used |= BA_MP_USED_TRUE;
  851. name = xstrdup_printf("%s", ba_node->coord_str);
  852. goto end_it;
  853. } else if (ba_request->conn_type[0] == SELECT_NAV)
  854. ba_request->conn_type[0] = bg_conf->default_conn_type[0];
  855. found = _find_x_path(results, ba_node,
  856. ba_node->coord,
  857. ba_request->geometry[X],
  858. 1,
  859. ba_request->conn_type[0], BLOCK_ALGO_FIRST);
  860. if (!found) {
  861. bool is_small = 0;
  862. if (ba_request->conn_type[0] == SELECT_SMALL)
  863. is_small = 1;
  864. debug2("trying less efficient code");
  865. remove_block(results, is_small);
  866. list_flush(results);
  867. list_append(results, ba_node);
  868. found = _find_x_path(results, ba_node,
  869. ba_node->coord,
  870. ba_request->geometry[X],
  871. 1,
  872. ba_request->conn_type[0],
  873. BLOCK_ALGO_SECOND);
  874. }
  875. if (found) {
  876. if (cluster_flags & CLUSTER_FLAG_BG) {
  877. List start_list = NULL;
  878. ListIterator itr;
  879. start_list = list_create(NULL);
  880. itr = list_iterator_create(results);
  881. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  882. list_append(start_list, ba_node);
  883. }
  884. list_iterator_destroy(itr);
  885. if (!_fill_in_coords(results,
  886. start_list,
  887. ba_request->geometry,
  888. ba_request->conn_type[0])) {
  889. list_destroy(start_list);
  890. goto end_it;
  891. }
  892. list_destroy(start_list);
  893. }
  894. } else {
  895. goto end_it;
  896. }
  897. name = _set_internal_wires(results,
  898. ba_request->size,
  899. ba_request->conn_type[0]);
  900. end_it:
  901. if (!send_results && results) {
  902. list_destroy(results);
  903. results = NULL;
  904. }
  905. if (name!=NULL) {
  906. debug2("name = %s", name);
  907. } else {
  908. debug2("can't allocate");
  909. xfree(name);
  910. }
  911. return name;
  912. }
  913. /* Rotate a 3-D geometry array through its six permutations */
  914. extern void ba_rotate_geo(uint16_t *req_geometry, int rot_cnt)
  915. {
  916. uint16_t tmp;
  917. switch (rot_cnt) {
  918. case 0: /* ABC -> ACB */
  919. case 2: /* CAB -> CBA */
  920. case 4: /* BCA -> BAC */
  921. SWAP(req_geometry[Y], req_geometry[Z], tmp);
  922. break;
  923. case 1: /* ACB -> CAB */
  924. case 3: /* CBA -> BCA */
  925. case 5: /* BAC -> ABC */
  926. SWAP(req_geometry[X], req_geometry[Y], tmp);
  927. break;
  928. }
  929. }
  930. /********************* Local Functions *********************/
  931. /*
  932. * This function is here to check options for rotating and elongating
  933. * and set up the request based on the count of each option
  934. */
  935. static int _check_for_options(select_ba_request_t* ba_request)
  936. {
  937. int temp;
  938. int set=0;
  939. uint16_t *geo = NULL;
  940. ListIterator itr;
  941. if (ba_request->rotate) {
  942. rotate_again:
  943. debug2("Rotating! %d",ba_request->rotate_count);
  944. if (ba_request->rotate_count==(cluster_dims-1)) {
  945. temp=ba_request->geometry[X];
  946. ba_request->geometry[X]=ba_request->geometry[Z];
  947. ba_request->geometry[Z]=temp;
  948. ba_request->rotate_count++;
  949. set=1;
  950. } else if (ba_request->rotate_count<(cluster_dims*2)) {
  951. temp=ba_request->geometry[X];
  952. ba_request->geometry[X]=ba_request->geometry[Y];
  953. ba_request->geometry[Y]=ba_request->geometry[Z];
  954. ba_request->geometry[Z]=temp;
  955. ba_request->rotate_count++;
  956. set=1;
  957. } else
  958. ba_request->rotate = false;
  959. if (set) {
  960. if (ba_request->geometry[X]<=DIM_SIZE[X]
  961. && ba_request->geometry[Y]<=DIM_SIZE[Y]
  962. && ba_request->geometry[Z]<=DIM_SIZE[Z])
  963. return 1;
  964. else {
  965. set = 0;
  966. goto rotate_again;
  967. }
  968. }
  969. }
  970. if (ba_request->elongate) {
  971. elongate_again:
  972. debug2("Elongating! %d",ba_request->elongate_count);
  973. ba_request->rotate_count=0;
  974. ba_request->rotate = true;
  975. set = 0;
  976. itr = list_iterator_create(ba_request->elongate_geos);
  977. for(set=0; set<=ba_request->elongate_count; set++)
  978. geo = list_next(itr);
  979. list_iterator_destroy(itr);
  980. if (geo == NULL)
  981. return 0;
  982. ba_request->elongate_count++;
  983. ba_request->geometry[X] = geo[X];
  984. ba_request->geometry[Y] = geo[Y];
  985. ba_request->geometry[Z] = geo[Z];
  986. if (ba_request->geometry[X]<=DIM_SIZE[X]
  987. && ba_request->geometry[Y]<=DIM_SIZE[Y]
  988. && ba_request->geometry[Z]<=DIM_SIZE[Z]) {
  989. return 1;
  990. } else
  991. goto elongate_again;
  992. }
  993. return 0;
  994. }
  995. /*
  996. * grab all the geometries that we can get and append them to the list geos
  997. */
  998. static int _append_geo(uint16_t *geometry, List geos, int rotate)
  999. {
  1000. ListIterator itr;
  1001. uint16_t *geo_ptr = NULL;
  1002. uint16_t *geo = NULL;
  1003. int temp_geo;
  1004. int i, j;
  1005. if (rotate) {
  1006. for (i = (cluster_dims - 1); i >= 0; i--) {
  1007. for (j = 1; j <= i; j++) {
  1008. if ((geometry[j-1] > geometry[j])
  1009. && (geometry[j] <= DIM_SIZE[j-i])
  1010. && (geometry[j-1] <= DIM_SIZE[j])) {
  1011. temp_geo = geometry[j-1];
  1012. geometry[j-1] = geometry[j];
  1013. geometry[j] = temp_geo;
  1014. }
  1015. }
  1016. }
  1017. }
  1018. itr = list_iterator_create(geos);
  1019. while ((geo_ptr = list_next(itr)) != NULL) {
  1020. if (geometry[X] == geo_ptr[X]
  1021. && geometry[Y] == geo_ptr[Y]
  1022. && geometry[Z] == geo_ptr[Z])
  1023. break;
  1024. }
  1025. list_iterator_destroy(itr);
  1026. if (geo_ptr == NULL) {
  1027. geo = xmalloc(sizeof(int)*cluster_dims);
  1028. geo[X] = geometry[X];
  1029. geo[Y] = geometry[Y];
  1030. geo[Z] = geometry[Z];
  1031. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1032. info("adding geo %c%c%c",
  1033. alpha_num[geo[X]], alpha_num[geo[Y]],
  1034. alpha_num[geo[Z]]);
  1035. list_append(geos, geo);
  1036. }
  1037. return 1;
  1038. }
  1039. /*
  1040. * Fill in the paths and extra midplanes we need for the block.
  1041. * Basically copy the x path sent in with the start_list in each Y and
  1042. * Z dimension filling in every midplane for the block and then
  1043. * completing the Y and Z wiring, tying the whole block together.
  1044. *
  1045. * IN/OUT results - total list of midplanes after this function
  1046. * returns successfully. Should be
  1047. * an exact copy of the start_list at first.
  1048. * IN start_list - exact copy of results at first, This should only be
  1049. * a list of midplanes on the X dim. We will work off this and
  1050. * the geometry to fill in this wiring for the X dim in all the
  1051. * Y and Z coords.
  1052. * IN geometry - What the block looks like
  1053. * IN conn_type - Mesh or Torus
  1054. *
  1055. * RET: 0 on failure 1 on success
  1056. */
  1057. static int _fill_in_coords(List results, List start_list,
  1058. uint16_t *geometry, int conn_type)
  1059. {
  1060. ba_mp_t *ba_node = NULL;
  1061. ba_mp_t *check_node = NULL;
  1062. int rc = 1;
  1063. ListIterator itr = NULL;
  1064. int y=0, z=0;
  1065. ba_switch_t *curr_switch = NULL;
  1066. ba_switch_t *next_switch = NULL;
  1067. if (!start_list || !results)
  1068. return 0;
  1069. /* go through the start_list and add all the midplanes */
  1070. itr = list_iterator_create(start_list);
  1071. while ((check_node = (ba_mp_t*) list_next(itr))) {
  1072. curr_switch = &check_node->axis_switch[X];
  1073. for(y=0; y<geometry[Y]; y++) {
  1074. if ((check_node->coord[Y]+y) >= DIM_SIZE[Y]) {
  1075. rc = 0;
  1076. goto failed;
  1077. }
  1078. for(z=0; z<geometry[Z]; z++) {
  1079. if ((check_node->coord[Z]+z) >= DIM_SIZE[Z]) {
  1080. rc = 0;
  1081. goto failed;
  1082. }
  1083. ba_node = &ba_main_grid
  1084. [check_node->coord[X]]
  1085. [check_node->coord[Y]+y]
  1086. [check_node->coord[Z]+z];
  1087. if ((ba_node->coord[Y] == check_node->coord[Y])
  1088. && (ba_node->coord[Z]
  1089. == check_node->coord[Z]))
  1090. continue;
  1091. if (!_node_used(ba_node, geometry[X])) {
  1092. if (ba_debug_flags
  1093. & DEBUG_FLAG_BG_ALGO_DEEP)
  1094. info("here Adding %c%c%c",
  1095. alpha_num[ba_node->
  1096. coord[X]],
  1097. alpha_num[ba_node->
  1098. coord[Y]],
  1099. alpha_num[ba_node->
  1100. coord[Z]]);
  1101. list_append(results, ba_node);
  1102. next_switch = &ba_node->axis_switch[X];
  1103. /* since we are going off the
  1104. * main system we can send NULL
  1105. * here
  1106. */
  1107. _copy_the_path(NULL, curr_switch,
  1108. next_switch,
  1109. 0, X);
  1110. } else {
  1111. rc = 0;
  1112. goto failed;
  1113. }
  1114. }
  1115. }
  1116. }
  1117. list_iterator_destroy(itr);
  1118. itr = list_iterator_create(start_list);
  1119. check_node = (ba_mp_t*) list_next(itr);
  1120. list_iterator_destroy(itr);
  1121. itr = list_iterator_create(results);
  1122. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  1123. if (!_find_yz_path(ba_node,
  1124. check_node->coord,
  1125. geometry,
  1126. conn_type)){
  1127. rc = 0;
  1128. goto failed;
  1129. }
  1130. }
  1131. if (deny_pass) {
  1132. if ((*deny_pass & PASS_DENY_Y)
  1133. && (*deny_pass & PASS_FOUND_Y)) {
  1134. debug("We don't allow Y passthoughs");
  1135. rc = 0;
  1136. } else if ((*deny_pass & PASS_DENY_Z)
  1137. && (*deny_pass & PASS_FOUND_Z)) {
  1138. debug("We don't allow Z passthoughs");
  1139. rc = 0;
  1140. }
  1141. }
  1142. failed:
  1143. list_iterator_destroy(itr);
  1144. return rc;
  1145. }
  1146. /*
  1147. * Copy a path through the wiring of a switch to another switch on a
  1148. * starting port on a dimension.
  1149. *
  1150. * IN/OUT: nodes - Local list of midplanes you are keeping track of. If
  1151. * you visit any new midplanes a copy from ba_main_grid
  1152. * will be added to the list. If NULL the path will be
  1153. * set in mark_switch of the main virtual system (ba_main_grid).
  1154. * IN: curr_switch - The switch you want to copy the path of
  1155. * IN/OUT: mark_switch - The switch you want to fill in. On success
  1156. * this switch will contain a complete path from the curr_switch
  1157. * starting from the source port.
  1158. * IN: source - source port number (If calling for the first time
  1159. * should be 0 since we are looking for 1 at the end)
  1160. * IN: dim - Dimension XYZ
  1161. *
  1162. * RET: on success 1, on error 0
  1163. */
  1164. static int _copy_the_path(List nodes, ba_switch_t *curr_switch,
  1165. ba_switch_t *mark_switch,
  1166. int source, int dim)
  1167. {
  1168. uint16_t *mp_tar;
  1169. uint16_t *mark_mp_tar;
  1170. uint16_t *node_curr;
  1171. uint16_t port_tar, port_tar1;
  1172. ba_switch_t *next_switch = NULL;
  1173. ba_switch_t *next_mark_switch = NULL;
  1174. /* Copy the source used and port_tar */
  1175. mark_switch->int_wire[source].used =
  1176. curr_switch->int_wire[source].used;
  1177. mark_switch->int_wire[source].port_tar =
  1178. curr_switch->int_wire[source].port_tar;
  1179. port_tar = curr_switch->int_wire[source].port_tar;
  1180. /* Now to the same thing from the other end */
  1181. mark_switch->int_wire[port_tar].used =
  1182. curr_switch->int_wire[port_tar].used;
  1183. mark_switch->int_wire[port_tar].port_tar =
  1184. curr_switch->int_wire[port_tar].port_tar;
  1185. port_tar1 = port_tar;
  1186. /* follow the path */
  1187. node_curr = curr_switch->ext_wire[0].mp_tar;
  1188. mp_tar = curr_switch->ext_wire[port_tar].mp_tar;
  1189. if (mark_switch->int_wire[source].used)
  1190. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1191. info("setting dim %d %c%c%c %d-> %c%c%c %d",
  1192. dim,
  1193. alpha_num[node_curr[X]],
  1194. alpha_num[node_curr[Y]],
  1195. alpha_num[node_curr[Z]],
  1196. source,
  1197. alpha_num[mp_tar[X]],
  1198. alpha_num[mp_tar[Y]],
  1199. alpha_num[mp_tar[Z]],
  1200. port_tar);
  1201. if (port_tar == 1) {
  1202. /* found the end of the line */
  1203. mark_switch->int_wire[1].used =
  1204. curr_switch->int_wire[1].used;
  1205. mark_switch->int_wire[1].port_tar =
  1206. curr_switch->int_wire[1].port_tar;
  1207. return 1;
  1208. }
  1209. mark_mp_tar = mark_switch->ext_wire[port_tar].mp_tar;
  1210. port_tar = curr_switch->ext_wire[port_tar].port_tar;
  1211. if (node_curr[X] == mp_tar[X]
  1212. && node_curr[Y] == mp_tar[Y]
  1213. && node_curr[Z] == mp_tar[Z]) {
  1214. /* We are going to the same node! this should never
  1215. happen */
  1216. debug5("something bad happened!! "
  1217. "we are on %c%c%c and are going to it "
  1218. "from port %d - > %d",
  1219. alpha_num[node_curr[X]],
  1220. alpha_num[node_curr[Y]],
  1221. alpha_num[node_curr[Z]],
  1222. port_tar1, port_tar);
  1223. return 0;
  1224. }
  1225. /* see what the next switch is going to be */
  1226. next_switch = &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]].
  1227. axis_switch[dim];
  1228. if (!nodes) {
  1229. /* If no nodes then just get the next switch to fill
  1230. in from the main system */
  1231. next_mark_switch = &ba_main_grid[mark_mp_tar[X]]
  1232. [mark_mp_tar[Y]]
  1233. [mark_mp_tar[Z]]
  1234. .axis_switch[dim];
  1235. } else {
  1236. ba_mp_t *ba_node = NULL;
  1237. ListIterator itr = list_iterator_create(nodes);
  1238. /* see if we have already been to this node */
  1239. while ((ba_node = list_next(itr))) {
  1240. if (ba_node->coord[X] == mark_mp_tar[X] &&
  1241. ba_node->coord[Y] == mark_mp_tar[Y] &&
  1242. ba_node->coord[Z] == mark_mp_tar[Z])
  1243. break; /* we found it */
  1244. }
  1245. list_iterator_destroy(itr);
  1246. if (!ba_node) {
  1247. /* If node grab a copy and add it to the list */
  1248. ba_node = ba_copy_mp(&ba_main_grid[mark_mp_tar[X]]
  1249. [mark_mp_tar[Y]]
  1250. [mark_mp_tar[Z]]);
  1251. ba_setup_mp(ba_node, false, false);
  1252. list_push(nodes, ba_node);
  1253. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1254. info("haven't seen %c%c%c adding it",
  1255. alpha_num[ba_node->coord[X]],
  1256. alpha_num[ba_node->coord[Y]],
  1257. alpha_num[ba_node->coord[Z]]);
  1258. }
  1259. next_mark_switch = &ba_node->axis_switch[dim];
  1260. }
  1261. /* Keep going until we reach the end of the line */
  1262. return _copy_the_path(nodes, next_switch, next_mark_switch,
  1263. port_tar, dim);
  1264. }
  1265. static int _find_yz_path(ba_mp_t *ba_node, uint16_t *first,
  1266. uint16_t *geometry, int conn_type)
  1267. {
  1268. ba_mp_t *next_node = NULL;
  1269. uint16_t *mp_tar = NULL;
  1270. ba_switch_t *dim_curr_switch = NULL;
  1271. ba_switch_t *dim_next_switch = NULL;
  1272. int i2;
  1273. int count = 0;
  1274. for(i2=1;i2<=2;i2++) {
  1275. if (geometry[i2] > 1) {
  1276. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1277. info("%d node %c%c%c port 2 -> ",
  1278. i2,
  1279. alpha_num[ba_node->coord[X]],
  1280. alpha_num[ba_node->coord[Y]],
  1281. alpha_num[ba_node->coord[Z]]);
  1282. dim_curr_switch = &ba_node->axis_switch[i2];
  1283. if (dim_curr_switch->int_wire[2].used) {
  1284. debug5("returning here");
  1285. return 0;
  1286. }
  1287. mp_tar = dim_curr_switch->ext_wire[2].mp_tar;
  1288. next_node =
  1289. &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]];
  1290. dim_next_switch = &next_node->axis_switch[i2];
  1291. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1292. info("%c%c%c port 5",
  1293. alpha_num[next_node->coord[X]],
  1294. alpha_num[next_node->coord[Y]],
  1295. alpha_num[next_node->coord[Z]]);
  1296. if (dim_next_switch->int_wire[5].used) {
  1297. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1298. info("returning here 2");
  1299. return 0;
  1300. }
  1301. debug5("%d %d %d %d",i2, mp_tar[i2],
  1302. first[i2], geometry[i2]);
  1303. /* Here we need to see where we are in
  1304. * reference to the geo of this dimension. If
  1305. * we have not gotten the number we need in
  1306. * the direction we just go to the next node
  1307. * with 5 -> 1. If we have all the midplanes
  1308. * we need then we go through and finish the
  1309. * torus if needed
  1310. */
  1311. if (mp_tar[i2] < first[i2])
  1312. count = mp_tar[i2]+(DIM_SIZE[i2]-first[i2]);
  1313. else
  1314. count = (mp_tar[i2]-first[i2]);
  1315. if (count == geometry[i2]) {
  1316. debug5("found end of me %c%c%c",
  1317. alpha_num[mp_tar[X]],
  1318. alpha_num[mp_tar[Y]],
  1319. alpha_num[mp_tar[Z]]);
  1320. if (conn_type == SELECT_TORUS) {
  1321. dim_curr_switch->int_wire[0].used = 1;
  1322. dim_curr_switch->int_wire[0].port_tar
  1323. = 2;
  1324. dim_curr_switch->int_wire[2].used = 1;
  1325. dim_curr_switch->int_wire[2].port_tar
  1326. = 0;
  1327. dim_curr_switch = dim_next_switch;
  1328. if (deny_pass
  1329. && (mp_tar[i2] != first[i2])) {
  1330. if (i2 == 1)
  1331. *deny_pass |=
  1332. PASS_FOUND_Y;
  1333. else
  1334. *deny_pass |=
  1335. PASS_FOUND_Z;
  1336. }
  1337. while (mp_tar[i2] != first[i2]) {
  1338. if (ba_debug_flags
  1339. & DEBUG_FLAG_BG_ALGO_DEEP)
  1340. info("on dim %d at %d "
  1341. "looking for %d",
  1342. i2,
  1343. mp_tar[i2],
  1344. first[i2]);
  1345. if (dim_curr_switch->
  1346. int_wire[2].used) {
  1347. if (ba_debug_flags
  1348. & DEBUG_FLAG_BG_ALGO_DEEP)
  1349. info("returning"
  1350. " here 3");
  1351. return 0;
  1352. }
  1353. dim_curr_switch->
  1354. int_wire[2].used = 1;
  1355. dim_curr_switch->
  1356. int_wire[2].port_tar
  1357. = 5;
  1358. dim_curr_switch->
  1359. int_wire[5].used
  1360. = 1;
  1361. dim_curr_switch->
  1362. int_wire[5].
  1363. port_tar = 2;
  1364. mp_tar = dim_curr_switch->
  1365. ext_wire[2].mp_tar;
  1366. next_node = &ba_main_grid
  1367. [mp_tar[X]]
  1368. [mp_tar[Y]]
  1369. [mp_tar[Z]];
  1370. dim_curr_switch =
  1371. &next_node->
  1372. axis_switch[i2];
  1373. }
  1374. if (ba_debug_flags
  1375. & DEBUG_FLAG_BG_ALGO_DEEP)
  1376. info("back to first on dim %d "
  1377. "at %d looking for %d",
  1378. i2,
  1379. mp_tar[i2],
  1380. first[i2]);
  1381. dim_curr_switch->
  1382. int_wire[5].used = 1;
  1383. dim_curr_switch->
  1384. int_wire[5].port_tar
  1385. = 1;
  1386. dim_curr_switch->
  1387. int_wire[1].used
  1388. = 1;
  1389. dim_curr_switch->
  1390. int_wire[1].
  1391. port_tar = 5;
  1392. }
  1393. } else if (count < geometry[i2]) {
  1394. if (conn_type == SELECT_TORUS ||
  1395. (conn_type == SELECT_MESH &&
  1396. (mp_tar[i2] != first[i2]))) {
  1397. dim_curr_switch->
  1398. int_wire[0].used = 1;
  1399. dim_curr_switch->
  1400. int_wire[0].port_tar
  1401. = 2;
  1402. dim_curr_switch->
  1403. int_wire[2].used
  1404. = 1;
  1405. dim_curr_switch->
  1406. int_wire[2].
  1407. port_tar = 0;
  1408. dim_next_switch->int_wire[5].used
  1409. = 1;
  1410. dim_next_switch->
  1411. int_wire[5].port_tar
  1412. = 1;
  1413. dim_next_switch->
  1414. int_wire[1].used = 1;
  1415. dim_next_switch->
  1416. int_wire[1].port_tar
  1417. = 5;
  1418. }
  1419. } else {
  1420. error("We were only looking for %d "
  1421. "in the %d dim, but now we have %d",
  1422. geometry[i2], i2, count);
  1423. return 0;
  1424. }
  1425. } else if ((geometry[i2] == 1) && (conn_type == SELECT_TORUS)) {
  1426. /* FIX ME: This is put here because we got
  1427. into a state where the Y dim was not being
  1428. processed correctly. This will set up the
  1429. 0 -> 1 port correctly. We should probably
  1430. find out why this was happening in the
  1431. first place though. A reproducer was to
  1432. have
  1433. MPs=[310x323] Type=TORUS
  1434. MPs=[200x233] Type=TORUS
  1435. MPs=[300x303] Type=TORUS
  1436. MPs=[100x133] Type=TORUS
  1437. MPs=[000x033] Type=TORUS
  1438. MPs=[400x433] Type=TORUS
  1439. and then add
  1440. MPs=[330x333] Type=TORUS
  1441. */
  1442. dim_curr_switch = &ba_node->axis_switch[i2];
  1443. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1444. info("%d node %c%c%c port 0 -> 1",
  1445. i2,
  1446. alpha_num[ba_node->coord[X]],
  1447. alpha_num[ba_node->coord[Y]],
  1448. alpha_num[ba_node->coord[Z]]);
  1449. dim_curr_switch->int_wire[0].used = 1;
  1450. dim_curr_switch->int_wire[0].port_tar = 1;
  1451. dim_curr_switch->int_wire[1].used = 1;
  1452. dim_curr_switch->int_wire[1].port_tar = 0;
  1453. }
  1454. }
  1455. return 1;
  1456. }
  1457. #ifndef HAVE_BG_FILES
  1458. /** */
  1459. static int _emulate_ext_wiring(ba_mp_t ***grid)
  1460. {
  1461. int x;
  1462. ba_mp_t *source = NULL, *target = NULL;
  1463. if (cluster_dims == 1) {
  1464. for(x=0;x<DIM_SIZE[X];x++) {
  1465. source = &grid[x][0][0];
  1466. if (x<(DIM_SIZE[X]-1))
  1467. target = &grid[x+1][0][0];
  1468. else
  1469. target = &grid[0][0][0];
  1470. _set_external_wires(X, x, source, target);
  1471. }
  1472. } else {
  1473. int y,z;
  1474. for(x=0;x<DIM_SIZE[X];x++) {
  1475. for(y=0;y<DIM_SIZE[Y];y++) {
  1476. for(z=0;z<DIM_SIZE[Z];z++) {
  1477. source = &grid[x][y][z];
  1478. if (x<(DIM_SIZE[X]-1)) {
  1479. target = &grid[x+1][y][z];
  1480. } else
  1481. target = &grid[0][y][z];
  1482. _set_external_wires(X, x, source,
  1483. target);
  1484. if (y<(DIM_SIZE[Y]-1))
  1485. target = &grid[x][y+1][z];
  1486. else
  1487. target = &grid[x][0][z];
  1488. _set_external_wires(Y, y, source,
  1489. target);
  1490. if (z<(DIM_SIZE[Z]-1))
  1491. target = &grid[x][y][z+1];
  1492. else
  1493. target = &grid[x][y][0];
  1494. _set_external_wires(Z, z, source,
  1495. target);
  1496. }
  1497. }
  1498. }
  1499. }
  1500. return 1;
  1501. }
  1502. #endif
  1503. static int _reset_the_path(ba_switch_t *curr_switch, int source,
  1504. int target, int dim)
  1505. {
  1506. uint16_t *mp_tar;
  1507. uint16_t *node_curr;
  1508. int port_tar, port_tar1;
  1509. ba_switch_t *next_switch = NULL;
  1510. if (source < 0 || source >= NUM_PORTS_PER_NODE) {
  1511. fatal("source port was %d can only be 0->%d",
  1512. source, NUM_PORTS_PER_NODE);
  1513. }
  1514. if (target < 0 || target >= NUM_PORTS_PER_NODE) {
  1515. fatal("target port was %d can only be 0->%d",
  1516. target, NUM_PORTS_PER_NODE);
  1517. }
  1518. /*set the switch to not be used */
  1519. if (!curr_switch->int_wire[source].used) {
  1520. /* This means something overlapping the removing block
  1521. already cleared this, or the path just never was
  1522. complete in the first place. */
  1523. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1524. info("I reached the end, the source isn't used");
  1525. return 1;
  1526. }
  1527. curr_switch->int_wire[source].used = 0;
  1528. port_tar = curr_switch->int_wire[source].port_tar;
  1529. if (port_tar < 0 || port_tar >= NUM_PORTS_PER_NODE) {
  1530. fatal("port_tar port was %d can only be 0->%d",
  1531. source, NUM_PORTS_PER_NODE);
  1532. return 1;
  1533. }
  1534. port_tar1 = port_tar;
  1535. curr_switch->int_wire[source].port_tar = source;
  1536. curr_switch->int_wire[port_tar].used = 0;
  1537. curr_switch->int_wire[port_tar].port_tar = port_tar;
  1538. if (port_tar == target) {
  1539. return 1;
  1540. }
  1541. /* follow the path */
  1542. node_curr = curr_switch->ext_wire[0].mp_tar;
  1543. mp_tar = curr_switch->ext_wire[port_tar].mp_tar;
  1544. port_tar = curr_switch->ext_wire[port_tar].port_tar;
  1545. if (source == port_tar1) {
  1546. debug("got this bad one %c%c%c %d %d -> %c%c%c %d",
  1547. alpha_num[node_curr[X]],
  1548. alpha_num[node_curr[Y]],
  1549. alpha_num[node_curr[Z]],
  1550. source,
  1551. port_tar1,
  1552. alpha_num[mp_tar[X]],
  1553. alpha_num[mp_tar[Y]],
  1554. alpha_num[mp_tar[Z]],
  1555. port_tar);
  1556. return 0;
  1557. }
  1558. debug5("from %c%c%c %d %d -> %c%c%c %d",
  1559. alpha_num[node_curr[X]],
  1560. alpha_num[node_curr[Y]],
  1561. alpha_num[node_curr[Z]],
  1562. source,
  1563. port_tar1,
  1564. alpha_num[mp_tar[X]],
  1565. alpha_num[mp_tar[Y]],
  1566. alpha_num[mp_tar[Z]],
  1567. port_tar);
  1568. if (node_curr[X] == mp_tar[X]
  1569. && node_curr[Y] == mp_tar[Y]
  1570. && node_curr[Z] == mp_tar[Z]) {
  1571. debug5("%d something bad happened!!", dim);
  1572. return 0;
  1573. }
  1574. next_switch =
  1575. &ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]].axis_switch[dim];
  1576. return _reset_the_path(next_switch, port_tar, target, dim);
  1577. // return 1;
  1578. }
  1579. extern void ba_create_system()
  1580. {
  1581. int x,y,z, i = 0;
  1582. if (ba_main_grid)
  1583. ba_destroy_system();
  1584. best_count=BEST_COUNT_INIT;
  1585. ba_main_grid = (ba_mp_t***)
  1586. xmalloc(sizeof(ba_mp_t**) * DIM_SIZE[X]);
  1587. for (x=0; x<DIM_SIZE[X]; x++) {
  1588. ba_main_grid[x] = (ba_mp_t**)
  1589. xmalloc(sizeof(ba_mp_t*) * DIM_SIZE[Y]);
  1590. for (y=0; y<DIM_SIZE[Y]; y++) {
  1591. ba_main_grid[x][y] = (ba_mp_t*)
  1592. xmalloc(sizeof(ba_mp_t)
  1593. * DIM_SIZE[Z]);
  1594. for (z=0; z<DIM_SIZE[Z]; z++){
  1595. ba_mp_t *ba_mp = &ba_main_grid[x][y][z];
  1596. ba_mp->coord[X] = x;
  1597. ba_mp->coord[Y] = y;
  1598. ba_mp->coord[Z] = z;
  1599. snprintf(ba_mp->coord_str,
  1600. sizeof(ba_mp->coord_str),
  1601. "%c%c%c",
  1602. alpha_num[ba_mp->coord[X]],
  1603. alpha_num[ba_mp->coord[Y]],
  1604. alpha_num[ba_mp->coord[Z]]);
  1605. ba_setup_mp(ba_mp, true, false);
  1606. ba_mp->state = NODE_STATE_IDLE;
  1607. /* This might get changed
  1608. later, but just incase set
  1609. it up here.
  1610. */
  1611. ba_mp->index = i++;
  1612. }
  1613. }
  1614. }
  1615. if ((cluster_flags & CLUSTER_FLAG_BGL) ||
  1616. (cluster_flags & CLUSTER_FLAG_BGP)) {
  1617. init_wires();
  1618. #ifndef HAVE_BG_FILES
  1619. _emulate_ext_wiring(ba_main_grid);
  1620. #endif
  1621. }
  1622. path = list_create(_delete_path_list);
  1623. best_path = list_create(_delete_path_list);
  1624. }
  1625. /** */
  1626. extern void ba_destroy_system(void)
  1627. {
  1628. int x, y;
  1629. if (path) {
  1630. list_destroy(path);
  1631. path = NULL;
  1632. }
  1633. if (best_path) {
  1634. list_destroy(best_path);
  1635. best_path = NULL;
  1636. }
  1637. #ifdef HAVE_BG_FILES
  1638. if (bg)
  1639. bridge_free_bg(bg);
  1640. #endif
  1641. _mp_map_initialized = false;
  1642. _wires_initialized = true;
  1643. if (ba_main_grid) {
  1644. for (x=0; x<DIM_SIZE[X]; x++) {
  1645. for (y=0; y<DIM_SIZE[Y]; y++)
  1646. xfree(ba_main_grid[x][y]);
  1647. xfree(ba_main_grid[x]);
  1648. }
  1649. xfree(ba_main_grid);
  1650. ba_main_grid = NULL;
  1651. }
  1652. }
  1653. extern bool ba_sub_block_in_bitmap(select_jobinfo_t *jobinfo,
  1654. bitstr_t *usable_bitmap, bool step)
  1655. {
  1656. /* This shouldn't be called. */
  1657. xassert(0);
  1658. return false;
  1659. }
  1660. extern int ba_sub_block_in_bitmap_clear(select_jobinfo_t *jobinfo,
  1661. bitstr_t *usable_bitmap)
  1662. {
  1663. /* this doesn't do anything since above doesn't. */
  1664. return SLURM_SUCCESS;
  1665. }
  1666. extern ba_mp_t *ba_sub_block_in_record(
  1667. bg_record_t *bg_record, uint32_t *node_count,
  1668. select_jobinfo_t *jobinfo)
  1669. {
  1670. /* This shouldn't be called. */
  1671. xassert(0);
  1672. return false;
  1673. }
  1674. extern int ba_sub_block_in_record_clear(
  1675. bg_record_t *bg_record, struct step_record *step_ptr)
  1676. {
  1677. /* this doesn't do anything since above doesn't. */
  1678. return SLURM_SUCCESS;
  1679. }
  1680. extern void ba_sync_job_to_block(bg_record_t *bg_record,
  1681. struct job_record *job_ptr)
  1682. {
  1683. xassert(bg_record);
  1684. xassert(job_ptr);
  1685. bg_record->job_running = job_ptr->job_id;
  1686. bg_record->job_ptr = job_ptr;
  1687. }
  1688. extern bitstr_t *ba_create_ba_mp_cnode_bitmap(bg_record_t *bg_record)
  1689. {
  1690. return NULL;
  1691. }
  1692. extern void ba_set_ionode_str(bg_record_t *bg_record)
  1693. {
  1694. char bitstring[BITSIZE];
  1695. if (!bg_record->ionode_bitmap)
  1696. return;
  1697. bit_fmt(bitstring, BITSIZE, bg_record->ionode_bitmap);
  1698. bg_record->ionode_str = xstrdup(bitstring);
  1699. }
  1700. extern struct job_record *ba_remove_job_in_block_job_list(
  1701. bg_record_t *bg_record, struct job_record *in_job_ptr)
  1702. {
  1703. return NULL;
  1704. }
  1705. static void _delete_path_list(void *object)
  1706. {
  1707. ba_path_switch_t *path_switch = (ba_path_switch_t *)object;
  1708. if (path_switch) {
  1709. xfree(path_switch);
  1710. }
  1711. return;
  1712. }
  1713. /**
  1714. * algorithm for finding match
  1715. */
  1716. static int _find_match(select_ba_request_t *ba_request, List results)
  1717. {
  1718. int x=0;
  1719. ba_mp_t *ba_node = NULL;
  1720. char *name=NULL;
  1721. int startx = DIM_SIZE[X]-1;
  1722. uint16_t *geo_ptr;
  1723. if (!(cluster_flags & CLUSTER_FLAG_BG))
  1724. return 0;
  1725. /* set up the geo here */
  1726. if (!(geo_ptr = list_peek(ba_request->elongate_geos)))
  1727. return 0;
  1728. ba_request->rotate_count=0;
  1729. ba_request->elongate_count=1;
  1730. ba_request->geometry[X] = geo_ptr[X];
  1731. ba_request->geometry[Y] = geo_ptr[Y];
  1732. ba_request->geometry[Z] = geo_ptr[Z];
  1733. if (ba_request->geometry[X]>DIM_SIZE[X]
  1734. || ba_request->geometry[Y]>DIM_SIZE[Y]
  1735. || ba_request->geometry[Z]>DIM_SIZE[Z])
  1736. if (!_check_for_options(ba_request))
  1737. return 0;
  1738. start_again:
  1739. x=0;
  1740. if (x == startx)
  1741. x = startx-1;
  1742. while (x!=startx) {
  1743. x++;
  1744. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1745. info("finding %c%c%c try %d",
  1746. alpha_num[ba_request->geometry[X]],
  1747. alpha_num[ba_request->geometry[Y]],
  1748. alpha_num[ba_request->geometry[Z]],
  1749. x);
  1750. new_node:
  1751. ba_node = coord2ba_mp(ba_request->start);
  1752. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1753. info("starting at %s", ba_node->coord_str);
  1754. if (!_node_used(ba_node, ba_request->geometry[X])) {
  1755. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1756. info("trying this node %s %c%c%c %d",
  1757. ba_node->coord_str,
  1758. alpha_num[ba_request->geometry[X]],
  1759. alpha_num[ba_request->geometry[Y]],
  1760. alpha_num[ba_request->geometry[Z]],
  1761. ba_request->conn_type[X]);
  1762. name = set_bg_block(results, ba_request);
  1763. if (name) {
  1764. ba_request->save_name = xstrdup(name);
  1765. xfree(name);
  1766. return 1;
  1767. }
  1768. if (results) {
  1769. bool is_small = 0;
  1770. if (ba_request->conn_type[0] == SELECT_SMALL)
  1771. is_small = 1;
  1772. remove_block(results, is_small);
  1773. list_flush(results);
  1774. }
  1775. if (ba_request->start_req)
  1776. goto requested_end;
  1777. //exit(0);
  1778. debug2("trying something else");
  1779. }
  1780. if ((DIM_SIZE[Z] - ba_request->start[Z]-1)
  1781. >= ba_request->geometry[Z])
  1782. ba_request->start[Z]++;
  1783. else {
  1784. ba_request->start[Z] = 0;
  1785. if ((DIM_SIZE[Y] - ba_request->start[Y]-1)
  1786. >= ba_request->geometry[Y])
  1787. ba_request->start[Y]++;
  1788. else {
  1789. ba_request->start[Y] = 0;
  1790. if ((DIM_SIZE[X] - ba_request->start[X]-1)
  1791. >= ba_request->geometry[X])
  1792. ba_request->start[X]++;
  1793. else {
  1794. if (ba_request->size == 1)
  1795. goto requested_end;
  1796. if (!_check_for_options(ba_request))
  1797. return 0;
  1798. else {
  1799. memset(ba_request->start, 0,
  1800. sizeof(ba_request->
  1801. start));
  1802. goto start_again;
  1803. }
  1804. }
  1805. }
  1806. }
  1807. goto new_node;
  1808. }
  1809. requested_end:
  1810. debug2("1 can't allocate");
  1811. return 0;
  1812. }
  1813. /*
  1814. * Used to check if midplane is usable in the block we are creating
  1815. *
  1816. * IN: ba_node - node to check if is used
  1817. * IN: x_size - How big is the block in the X dim used to see if the
  1818. * wires are full hence making this midplane unusable.
  1819. */
  1820. static bool _node_used(ba_mp_t* ba_node, int x_size)
  1821. {
  1822. ba_switch_t* ba_switch = NULL;
  1823. /* if we've used this node in another block already */
  1824. if (!ba_node || ba_node->used) {
  1825. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1826. info("node %s used", ba_node->coord_str);
  1827. return true;
  1828. }
  1829. /* Check If we've used this node's switches completely in another
  1830. block already. Right now we are only needing to look at
  1831. the X dim since it is the only one with extra wires. This
  1832. can be set up to do all the dim's if in the future if it is
  1833. needed. We only need to check this if we are planning on
  1834. using more than 1 midplane in the block creation */
  1835. if (x_size > 1) {
  1836. /* get the switch of the X Dimension */
  1837. ba_switch = &ba_node->axis_switch[X];
  1838. /* If both of these ports are used then the node
  1839. is in use since there are no more wires we
  1840. can use since these can not connect to each
  1841. other they must be connected to the other ports.
  1842. */
  1843. if (ba_switch->int_wire[3].used
  1844. && ba_switch->int_wire[5].used) {
  1845. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  1846. info("switch full in the X dim on node %s!",
  1847. ba_node->coord_str);
  1848. return true;
  1849. }
  1850. }
  1851. return false;
  1852. }
  1853. static void _switch_config(ba_mp_t* source, ba_mp_t* target, int dim,
  1854. int port_src, int port_tar)
  1855. {
  1856. ba_switch_t* config = NULL, *config_tar = NULL;
  1857. int i;
  1858. if (!source || !target)
  1859. return;
  1860. config = &source->axis_switch[dim];
  1861. config_tar = &target->axis_switch[dim];
  1862. for(i=0;i<cluster_dims;i++) {
  1863. /* Set the coord of the source target node to the target */
  1864. config->ext_wire[port_src].mp_tar[i] = target->coord[i];
  1865. /* Set the coord of the target back to the source */
  1866. config_tar->ext_wire[port_tar].mp_tar[i] = source->coord[i];
  1867. }
  1868. /* Set the port of the source target node to the target */
  1869. config->ext_wire[port_src].port_tar = port_tar;
  1870. /* Set the port of the target back to the source */
  1871. config_tar->ext_wire[port_tar].port_tar = port_src;
  1872. }
  1873. static int _set_external_wires(int dim, int count, ba_mp_t* source,
  1874. ba_mp_t* target)
  1875. {
  1876. #ifdef HAVE_BG_FILES
  1877. #ifdef HAVE_BGL
  1878. #define UNDER_POS 7
  1879. #define NODE_LEN 5
  1880. #define VAL_NAME_LEN 12
  1881. #else
  1882. #define UNDER_POS 9
  1883. #define NODE_LEN 7
  1884. #define VAL_NAME_LEN 16
  1885. #endif
  1886. int rc;
  1887. int i;
  1888. rm_wire_t *my_wire = NULL;
  1889. rm_port_t *my_port = NULL;
  1890. char *wire_id = NULL;
  1891. int from_port, to_port;
  1892. int wire_num;
  1893. char from_node[NODE_LEN];
  1894. char to_node[NODE_LEN];
  1895. if (working_cluster_rec) {
  1896. error("Can't do this cross-cluster");
  1897. return -1;
  1898. }
  1899. if (!have_db2) {
  1900. error("Can't access DB2 library, run from service node");
  1901. return -1;
  1902. }
  1903. if (!bg) {
  1904. if ((rc = bridge_get_bg(&bg)) != SLURM_SUCCESS) {
  1905. error("bridge_get_BG(): %d", rc);
  1906. return -1;
  1907. }
  1908. }
  1909. if (bg == NULL)
  1910. return -1;
  1911. if ((rc = bridge_get_data(bg, RM_WireNum, &wire_num))
  1912. != SLURM_SUCCESS) {
  1913. error("bridge_get_data(RM_BPNum): %d", rc);
  1914. wire_num = 0;
  1915. }
  1916. /* find out system wires on each mp */
  1917. for (i=0; i<wire_num; i++) {
  1918. if (i) {
  1919. if ((rc = bridge_get_data(bg, RM_NextWire, &my_wire))
  1920. != SLURM_SUCCESS) {
  1921. error("bridge_get_data(RM_NextWire): %d", rc);
  1922. break;
  1923. }
  1924. } else {
  1925. if ((rc = bridge_get_data(bg, RM_FirstWire, &my_wire))
  1926. != SLURM_SUCCESS) {
  1927. error("bridge_get_data(RM_FirstWire): %d", rc);
  1928. break;
  1929. }
  1930. }
  1931. if ((rc = bridge_get_data(my_wire, RM_WireID, &wire_id))
  1932. != SLURM_SUCCESS) {
  1933. error("bridge_get_data(RM_FirstWire): %d", rc);
  1934. break;
  1935. }
  1936. if (!wire_id) {
  1937. error("No Wire ID was returned from database");
  1938. continue;
  1939. }
  1940. if (wire_id[UNDER_POS] != '_')
  1941. continue;
  1942. switch(wire_id[0]) {
  1943. case 'X':
  1944. dim = X;
  1945. break;
  1946. case 'Y':
  1947. dim = Y;
  1948. break;
  1949. case 'Z':
  1950. dim = Z;
  1951. break;
  1952. }
  1953. if (strlen(wire_id) < VAL_NAME_LEN) {
  1954. error("Wire_id isn't correct %s",wire_id);
  1955. continue;
  1956. }
  1957. memset(&from_node, 0, sizeof(from_node));
  1958. memset(&to_node, 0, sizeof(to_node));
  1959. strncpy(from_node, wire_id+2, NODE_LEN-1);
  1960. strncpy(to_node, wire_id+UNDER_POS+1, NODE_LEN-1);
  1961. free(wire_id);
  1962. if ((rc = bridge_get_data(my_wire, RM_WireFromPort, &my_port))
  1963. != SLURM_SUCCESS) {
  1964. error("bridge_get_data(RM_FirstWire): %d", rc);
  1965. break;
  1966. }
  1967. if ((rc = bridge_get_data(my_port, RM_PortID, &from_port))
  1968. != SLURM_SUCCESS) {
  1969. error("bridge_get_data(RM_PortID): %d", rc);
  1970. break;
  1971. }
  1972. if ((rc = bridge_get_data(my_wire, RM_WireToPort, &my_port))
  1973. != SLURM_SUCCESS) {
  1974. error("bridge_get_data(RM_WireToPort): %d", rc);
  1975. break;
  1976. }
  1977. if ((rc = bridge_get_data(my_port, RM_PortID, &to_port))
  1978. != SLURM_SUCCESS) {
  1979. error("bridge_get_data(RM_PortID): %d", rc);
  1980. break;
  1981. }
  1982. source = loc2ba_mp(from_node);
  1983. if (!source) {
  1984. error("1 loc2ba_mp: mpid %s not known", from_node);
  1985. continue;
  1986. }
  1987. if (!validate_coord(source->coord))
  1988. continue;
  1989. target = loc2ba_mp(to_node);
  1990. if (!target) {
  1991. error("2 loc2ba_mp: mpid %s not known", to_node);
  1992. continue;
  1993. }
  1994. if (!validate_coord(target->coord))
  1995. continue;
  1996. _switch_config(source, target, dim, from_port, to_port);
  1997. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  1998. info("dim %d from %s %d -> %s %d",
  1999. dim,
  2000. source->coord_str,
  2001. from_port,
  2002. target->coord_str,
  2003. to_port);
  2004. }
  2005. #else
  2006. _switch_config(source, source, dim, 0, 0);
  2007. _switch_config(source, source, dim, 1, 1);
  2008. if (dim!=X) {
  2009. _switch_config(source, target, dim, 2, 5);
  2010. _switch_config(source, source, dim, 3, 3);
  2011. _switch_config(source, source, dim, 4, 4);
  2012. return 1;
  2013. }
  2014. if (cluster_dims == 1) {
  2015. if (count == 0)
  2016. _switch_config(source, source, dim, 5, 5);
  2017. else if (count < DIM_SIZE[X]-1)
  2018. _switch_config(source, target, dim, 2, 5);
  2019. else
  2020. _switch_config(source, source, dim, 2, 2);
  2021. _switch_config(source, source, dim, 3, 3);
  2022. _switch_config(source, source, dim, 4, 4);
  2023. return 1;
  2024. }
  2025. /* set up x */
  2026. /* always 2->5 of next. If it is the last it will go to the first.*/
  2027. _switch_config(source, target, dim, 2, 5);
  2028. /* set up split x */
  2029. if (DIM_SIZE[X] == 1) {
  2030. } else if (DIM_SIZE[X] == 4) {
  2031. switch(count) {
  2032. case 0:
  2033. case 3:
  2034. /* 0 and 3rd Node */
  2035. /* nothing */
  2036. break;
  2037. case 1:
  2038. /* 1st Node */
  2039. target = &ba_main_grid[0]
  2040. [source->coord[Y]]
  2041. [source->coord[Z]];
  2042. /* 4->3 of 0th */
  2043. _switch_config(source, target, dim, 4, 3);
  2044. break;
  2045. case 2:
  2046. /* 2nd Node */
  2047. target = &ba_main_grid[3]
  2048. [source->coord[Y]]
  2049. [source->coord[Z]];
  2050. /* 4->3 of 3rd and back */
  2051. _switch_config(source, target, dim, 4, 3);
  2052. _switch_config(source, target, dim, 3, 4);
  2053. break;
  2054. default:
  2055. fatal("got %d for a count on a %d X-dim system",
  2056. count, DIM_SIZE[X]);
  2057. break;
  2058. }
  2059. } else if (DIM_SIZE[X] == 5) {
  2060. /* 4 X dim fixes for wires */
  2061. switch(count) {
  2062. case 0:
  2063. case 2:
  2064. /* 0th and 2nd node */
  2065. /* Only the 2-5 is used here
  2066. so nothing else */
  2067. break;
  2068. case 1:
  2069. /* 1st node */
  2070. /* change target to 4th node */
  2071. target = &ba_main_grid[4]
  2072. [source->coord[Y]]
  2073. [source->coord[Z]];
  2074. /* 4->3 of 4th */
  2075. _switch_config(source, target, dim, 4, 3);
  2076. break;
  2077. case 3:
  2078. /* 3rd node */
  2079. /* change target to 2th node */
  2080. target = &ba_main_grid[2]
  2081. [source->coord[Y]]
  2082. [source->coord[Z]];
  2083. /* 4->3 of 2nd */
  2084. _switch_config(source, target, dim, 4, 3);
  2085. break;
  2086. case 4:
  2087. /* 4th node */
  2088. /* change target to 1st node */
  2089. target = &ba_main_grid[1]
  2090. [source->coord[Y]]
  2091. [source->coord[Z]];
  2092. /* 4->3 of 1st */
  2093. _switch_config(source, target, dim, 4, 3);
  2094. break;
  2095. default:
  2096. fatal("got %d for a count on a %d X-dim system",
  2097. count, DIM_SIZE[X]);
  2098. break;
  2099. }
  2100. } else if (DIM_SIZE[X] == 8) {
  2101. switch(count) {
  2102. case 0:
  2103. case 4:
  2104. /* 0 and 4th Node */
  2105. /* nothing */
  2106. break;
  2107. case 1:
  2108. case 5:
  2109. /* 1st Node */
  2110. target = &ba_main_grid[count-1]
  2111. [source->coord[Y]]
  2112. [source->coord[Z]];
  2113. /* 4->3 of previous */
  2114. _switch_config(source, target, dim, 4, 3);
  2115. break;
  2116. case 2:
  2117. /* 2nd Node */
  2118. target = &ba_main_grid[7]
  2119. [source->coord[Y]]
  2120. [source->coord[Z]];
  2121. /* 4->3 of last */
  2122. _switch_config(source, target, dim, 4, 3);
  2123. break;
  2124. case 3:
  2125. /* 3rd Node */
  2126. target = &ba_main_grid[6]
  2127. [source->coord[Y]]
  2128. [source->coord[Z]];
  2129. /* 4->3 of 6th */
  2130. _switch_config(source, target, dim, 4, 3);
  2131. break;
  2132. case 6:
  2133. /* 6th Node */
  2134. target = &ba_main_grid[3]
  2135. [source->coord[Y]]
  2136. [source->coord[Z]];
  2137. /* 4->3 of 3rd */
  2138. _switch_config(source, target, dim, 4, 3);
  2139. break;
  2140. case 7:
  2141. /* 7th Node */
  2142. target = &ba_main_grid[2]
  2143. [source->coord[Y]]
  2144. [source->coord[Z]];
  2145. /* 4->3 of 2nd */
  2146. _switch_config(source, target, dim, 4, 3);
  2147. break;
  2148. default:
  2149. fatal("got %d for a count on a %d X-dim system",
  2150. count, DIM_SIZE[X]);
  2151. break;
  2152. }
  2153. } else if (DIM_SIZE[X] == 9) {
  2154. switch(count) {
  2155. case 0:
  2156. case 4:
  2157. /* 0 and 4th Node */
  2158. /* nothing */
  2159. case 5:
  2160. case 6:
  2161. case 7:
  2162. /*already handled below */
  2163. break;
  2164. case 1:
  2165. /* 1st Node */
  2166. target = &ba_main_grid[7]
  2167. [source->coord[Y]]
  2168. [source->coord[Z]];
  2169. /* 4->3 of 7th and back */
  2170. _switch_config(source, target, dim, 4, 3);
  2171. _switch_config(target, source, dim, 4, 3);
  2172. break;
  2173. case 2:
  2174. /* 2nd Node */
  2175. target = &ba_main_grid[6]
  2176. [source->coord[Y]]
  2177. [source->coord[Z]];
  2178. /* 4->3 of 6th and back */
  2179. _switch_config(source, target, dim, 4, 3);
  2180. _switch_config(target, source, dim, 4, 3);
  2181. break;
  2182. case 3:
  2183. /* 3rd Node */
  2184. target = &ba_main_grid[5]
  2185. [source->coord[Y]]
  2186. [source->coord[Z]];
  2187. /* 4->3 of 5th and back */
  2188. _switch_config(source, target, dim, 4, 3);
  2189. _switch_config(target, source, dim, 4, 3);
  2190. break;
  2191. case 8:
  2192. /* 8th Node */
  2193. target = &ba_main_grid[0]
  2194. [source->coord[Y]]
  2195. [source->coord[Z]];
  2196. /* 4->3 of 0th */
  2197. _switch_config(source, target, dim, 4, 3);
  2198. break;
  2199. default:
  2200. fatal("got %d for a count on a %d X-dim system",
  2201. count, DIM_SIZE[X]);
  2202. break;
  2203. }
  2204. } else if (DIM_SIZE[X] == 13) {
  2205. int temp_num = 0;
  2206. switch(count) {
  2207. case 0:
  2208. case 6:
  2209. /* 0 and 6th Node no split */
  2210. case 8:
  2211. case 9:
  2212. case 10:
  2213. case 11:
  2214. case 12:
  2215. /* already taken care of in the next case so
  2216. * do nothing
  2217. */
  2218. break;
  2219. case 1:
  2220. case 2:
  2221. case 3:
  2222. case 4:
  2223. case 5:
  2224. /* get the node count - 1 then subtract it
  2225. * from 12 to get the new target and then go
  2226. * from 4->3 and back again
  2227. */
  2228. temp_num = 12 - (count - 1);
  2229. if (temp_num < 5)
  2230. fatal("node %d shouldn't go to %d",
  2231. count, temp_num);
  2232. target = &ba_main_grid[temp_num]
  2233. [source->coord[Y]]
  2234. [source->coord[Z]];
  2235. /* 4->3 */
  2236. _switch_config(source, target, dim, 4, 3);
  2237. /* and back 4->3 */
  2238. _switch_config(target, source, dim, 4, 3);
  2239. break;
  2240. case 7:
  2241. /* 7th Node */
  2242. target = &ba_main_grid[count-1]
  2243. [source->coord[Y]]
  2244. [source->coord[Z]];
  2245. /* 4->3 of previous */
  2246. _switch_config(source, target, dim, 4, 3);
  2247. break;
  2248. default:
  2249. fatal("got %d for a count on a %d X-dim system",
  2250. count, DIM_SIZE[X]);
  2251. break;
  2252. }
  2253. } else {
  2254. fatal("We don't have a config to do a BG system with %d "
  2255. "in the X-dim.", DIM_SIZE[X]);
  2256. }
  2257. #endif
  2258. return 1;
  2259. }
  2260. static char *_set_internal_wires(List nodes, int size, int conn_type)
  2261. {
  2262. ba_mp_t* ba_node[size+1];
  2263. int count=0, i;
  2264. uint16_t *start = NULL;
  2265. uint16_t *end = NULL;
  2266. char *name = NULL;
  2267. ListIterator itr;
  2268. hostlist_t hostlist;
  2269. if (!nodes)
  2270. return NULL;
  2271. hostlist = hostlist_create(NULL);
  2272. itr = list_iterator_create(nodes);
  2273. while ((ba_node[count] = list_next(itr))) {
  2274. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2275. info("name = %s", ba_node[count]->coord_str);
  2276. hostlist_push(hostlist, ba_node[count]->coord_str);
  2277. count++;
  2278. }
  2279. list_iterator_destroy(itr);
  2280. start = ba_node[0]->coord;
  2281. end = ba_node[count-1]->coord;
  2282. name = hostlist_ranged_string_xmalloc(hostlist);
  2283. hostlist_destroy(hostlist);
  2284. for (i=0;i<count;i++) {
  2285. if (!ba_node[i]->used) {
  2286. ba_node[i]->used |= BA_MP_USED_TRUE;
  2287. } else {
  2288. debug("No network connection to create "
  2289. "bgblock containing %s", name);
  2290. debug("Use smap to define bgblocks in "
  2291. "bluegene.conf");
  2292. xfree(name);
  2293. return NULL;
  2294. }
  2295. }
  2296. if (conn_type == SELECT_TORUS)
  2297. for (i=0;i<count;i++) {
  2298. _set_one_dim(start, end, ba_node[i]->coord);
  2299. }
  2300. return name;
  2301. }
  2302. /*
  2303. * Used to find a complete path based on the conn_type for an x dim.
  2304. * When starting to wire a block together this should be called first.
  2305. *
  2306. * IN/OUT: results - contains the number of midplanes we are
  2307. * potentially going to use in the X dim.
  2308. * IN: ba_node - current node we are looking at and have already added
  2309. * to results.
  2310. * IN: start - coordinates of the first midplane (so we know when when
  2311. * to end with a torus)
  2312. * IN: x_size - How many midplanes are we looking for in the X dim
  2313. * IN: found - count of how many midplanes we have found in the x dim
  2314. * IN: conn_type - MESH or TORUS
  2315. * IN: algo - algorythm to try an allocation by
  2316. *
  2317. * RET: 0 on failure, 1 on success
  2318. */
  2319. static int _find_x_path(List results, ba_mp_t *ba_node,
  2320. uint16_t *start, int x_size,
  2321. int found, int conn_type, block_algo_t algo)
  2322. {
  2323. ba_switch_t *curr_switch = NULL;
  2324. ba_switch_t *next_switch = NULL;
  2325. int port_tar = 0;
  2326. int source_port=0;
  2327. int target_port=1;
  2328. int broke = 0, not_first = 0;
  2329. int ports_to_try[2] = {4, 2};
  2330. uint16_t *mp_tar = NULL;
  2331. int i = 0;
  2332. ba_mp_t *next_node = NULL;
  2333. ba_mp_t *check_node = NULL;
  2334. /* int highest_phys_x = x_size - start[X]; */
  2335. /* info("highest_phys_x is %d", highest_phys_x); */
  2336. ListIterator itr = NULL;
  2337. if (!ba_node || !results || !start)
  2338. return 0;
  2339. curr_switch = &ba_node->axis_switch[X];
  2340. /* we don't need to go any further */
  2341. if (x_size == 1) {
  2342. /* Only set this if Torus since mesh doesn't have any
  2343. * connections in this path */
  2344. if (conn_type == SELECT_TORUS) {
  2345. curr_switch->int_wire[source_port].used = 1;
  2346. curr_switch->int_wire[source_port].port_tar =
  2347. target_port;
  2348. curr_switch->int_wire[target_port].used = 1;
  2349. curr_switch->int_wire[target_port].port_tar =
  2350. source_port;
  2351. }
  2352. return 1;
  2353. }
  2354. if (algo == BLOCK_ALGO_FIRST) {
  2355. ports_to_try[0] = 4;
  2356. ports_to_try[1] = 2;
  2357. } else if (algo == BLOCK_ALGO_SECOND) {
  2358. ports_to_try[0] = 2;
  2359. ports_to_try[1] = 4;
  2360. } else {
  2361. error("Unknown algo %d", algo);
  2362. return 0;
  2363. }
  2364. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2365. info("Algo(%d) found - %d", algo, found);
  2366. /* Check the 2 ports we can leave though in ports_to_try */
  2367. for(i=0;i<2;i++) {
  2368. /* info("trying port %d", ports_to_try[i]); */
  2369. /* check to make sure it isn't used */
  2370. if (!curr_switch->int_wire[ports_to_try[i]].used) {
  2371. /* looking at the next node on the switch
  2372. and it's port we are going to */
  2373. mp_tar = curr_switch->
  2374. ext_wire[ports_to_try[i]].mp_tar;
  2375. port_tar = curr_switch->
  2376. ext_wire[ports_to_try[i]].port_tar;
  2377. /* info("%c%c%c port %d goes to %c%c%c port %d", */
  2378. /* alpha_num[ba_node->coord[X]], */
  2379. /* alpha_num[ba_node->coord[Y]], */
  2380. /* alpha_num[ba_node->coord[Z]], */
  2381. /* ports_to_try[i], */
  2382. /* alpha_num[mp_tar[X]], */
  2383. /* alpha_num[mp_tar[Y]], */
  2384. /* alpha_num[mp_tar[Z]], */
  2385. /* port_tar); */
  2386. /* check to see if we are back at the start of the
  2387. block */
  2388. if ((mp_tar[X] == start[X]
  2389. && mp_tar[Y] == start[Y]
  2390. && mp_tar[Z] == start[Z])) {
  2391. broke = 1;
  2392. goto broke_it;
  2393. }
  2394. /* check to see if the port points to itself */
  2395. if ((mp_tar[X] == ba_node->coord[X]
  2396. && mp_tar[Y] == ba_node->coord[Y]
  2397. && mp_tar[Z] == ba_node->coord[Z])) {
  2398. continue;
  2399. }
  2400. /* check to see if I am going to a place I have
  2401. already been before */
  2402. itr = list_iterator_create(results);
  2403. while ((next_node = list_next(itr))) {
  2404. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2405. info("Algo(%d) looking at %c%c%c "
  2406. "and %c%c%c",
  2407. algo,
  2408. alpha_num[next_node->coord[X]],
  2409. alpha_num[next_node->coord[Y]],
  2410. alpha_num[next_node->coord[Z]],
  2411. alpha_num[mp_tar[X]],
  2412. alpha_num[mp_tar[Y]],
  2413. alpha_num[mp_tar[Z]]);
  2414. if ((mp_tar[X] == next_node->coord[X]
  2415. && mp_tar[Y] == next_node->coord[Y]
  2416. && mp_tar[Z] == next_node->coord[Z])) {
  2417. not_first = 1;
  2418. break;
  2419. }
  2420. }
  2421. list_iterator_destroy(itr);
  2422. if (not_first && found < DIM_SIZE[X]) {
  2423. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2424. info("Algo(%d) already been there "
  2425. "before", algo);
  2426. not_first = 0;
  2427. continue;
  2428. }
  2429. not_first = 0;
  2430. broke_it:
  2431. next_node = &ba_main_grid[mp_tar[X]]
  2432. [mp_tar[Y]]
  2433. [mp_tar[Z]];
  2434. next_switch = &next_node->axis_switch[X];
  2435. if ((conn_type == SELECT_MESH) && (found == (x_size))) {
  2436. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2437. info("Algo(%d) we found the end of "
  2438. "the mesh", algo);
  2439. return 1;
  2440. }
  2441. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2442. info("Algo(%d) Broke = %d Found = %d "
  2443. "x_size = %d",
  2444. algo, broke, found, x_size);
  2445. if (broke && (found == x_size)) {
  2446. goto found_path;
  2447. } else if (found == x_size) {
  2448. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2449. info("Algo(%d) finishing the torus!",
  2450. algo);
  2451. if (deny_pass && (*deny_pass & PASS_DENY_X)) {
  2452. info("we don't allow passthroughs 1");
  2453. return 0;
  2454. }
  2455. if (best_path)
  2456. list_flush(best_path);
  2457. else
  2458. best_path =
  2459. list_create(_delete_path_list);
  2460. if (path)
  2461. list_flush(path);
  2462. else
  2463. path = list_create(_delete_path_list);
  2464. _finish_torus(results,
  2465. curr_switch, 0, X, 0, start);
  2466. if (best_count < BEST_COUNT_INIT) {
  2467. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2468. info("Algo(%d) Found a best "
  2469. "path with %d steps.",
  2470. algo, best_count);
  2471. _set_best_path();
  2472. return 1;
  2473. } else {
  2474. return 0;
  2475. }
  2476. } else if (broke) {
  2477. broke = 0;
  2478. continue;
  2479. }
  2480. if (!_node_used(next_node, x_size)) {
  2481. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2482. info("Algo(%d) found %d looking at "
  2483. "%c%c%c %d going to %c%c%c %d",
  2484. algo,
  2485. found,
  2486. alpha_num[ba_node->coord[X]],
  2487. alpha_num[ba_node->coord[Y]],
  2488. alpha_num[ba_node->coord[Z]],
  2489. ports_to_try[i],
  2490. alpha_num[mp_tar[X]],
  2491. alpha_num[mp_tar[Y]],
  2492. alpha_num[mp_tar[Z]],
  2493. port_tar);
  2494. itr = list_iterator_create(results);
  2495. while ((check_node = list_next(itr))) {
  2496. if ((mp_tar[X] == check_node->coord[X]
  2497. && mp_tar[Y] ==
  2498. check_node->coord[Y]
  2499. && mp_tar[Z] ==
  2500. check_node->coord[Z])) {
  2501. break;
  2502. }
  2503. }
  2504. list_iterator_destroy(itr);
  2505. if (!check_node) {
  2506. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2507. info("Algo(%d) add %c%c%c",
  2508. algo,
  2509. alpha_num[next_node->
  2510. coord[X]],
  2511. alpha_num[next_node->
  2512. coord[Y]],
  2513. alpha_num[next_node->
  2514. coord[Z]]);
  2515. list_append(results, next_node);
  2516. } else {
  2517. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2518. info("Algo(%d) Hey this is "
  2519. "already added %c%c%c",
  2520. algo,
  2521. alpha_num[mp_tar[X]],
  2522. alpha_num[mp_tar[Y]],
  2523. alpha_num[mp_tar[Z]]);
  2524. continue;
  2525. }
  2526. found++;
  2527. /* look for the next closest midplane */
  2528. if (!_find_x_path(results, next_node,
  2529. start, x_size,
  2530. found, conn_type, algo)) {
  2531. _remove_node(results, next_node->coord);
  2532. found--;
  2533. continue;
  2534. } else {
  2535. found_path:
  2536. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2537. info("Algo(%d) added node "
  2538. "%c%c%c %d %d -> "
  2539. "%c%c%c %d %d",
  2540. algo,
  2541. alpha_num[ba_node->
  2542. coord[X]],
  2543. alpha_num[ba_node->
  2544. coord[Y]],
  2545. alpha_num[ba_node->
  2546. coord[Z]],
  2547. source_port,
  2548. ports_to_try[i],
  2549. alpha_num[mp_tar[X]],
  2550. alpha_num[mp_tar[Y]],
  2551. alpha_num[mp_tar[Z]],
  2552. port_tar,
  2553. target_port);
  2554. curr_switch->int_wire[source_port].used
  2555. = 1;
  2556. curr_switch->int_wire
  2557. [source_port].port_tar
  2558. = ports_to_try[i];
  2559. curr_switch->int_wire
  2560. [ports_to_try[i]].used = 1;
  2561. curr_switch->int_wire
  2562. [ports_to_try[i]].port_tar
  2563. = source_port;
  2564. next_switch->int_wire[port_tar].used
  2565. = 1;
  2566. next_switch->int_wire[port_tar].port_tar
  2567. = target_port;
  2568. next_switch->int_wire[target_port].used
  2569. = 1;
  2570. next_switch->int_wire
  2571. [target_port].port_tar
  2572. = port_tar;
  2573. return 1;
  2574. }
  2575. }
  2576. }
  2577. }
  2578. if (algo == BLOCK_ALGO_FIRST) {
  2579. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2580. info("Algo(%d) couldn't find path", algo);
  2581. return 0;
  2582. } else if (algo == BLOCK_ALGO_SECOND) {
  2583. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2584. info("Algo(%d) looking for the next free node "
  2585. "starting at %c%c%c",
  2586. algo,
  2587. alpha_num[ba_node->coord[X]],
  2588. alpha_num[ba_node->coord[Y]],
  2589. alpha_num[ba_node->coord[Z]]);
  2590. if (best_path)
  2591. list_flush(best_path);
  2592. else
  2593. best_path = list_create(_delete_path_list);
  2594. if (path)
  2595. list_flush(path);
  2596. else
  2597. path = list_create(_delete_path_list);
  2598. _find_next_free_using_port_2(curr_switch, 0, results, X, 0);
  2599. if (best_count < BEST_COUNT_INIT) {
  2600. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2601. info("Algo(%d) yes found next free %d", algo,
  2602. best_count);
  2603. mp_tar = _set_best_path();
  2604. if (deny_pass && (*deny_pass & PASS_DENY_X)
  2605. && (*deny_pass & PASS_FOUND_X)) {
  2606. debug("We don't allow X passthoughs.");
  2607. return 0;
  2608. }
  2609. /* info("got here with %c%c%c", */
  2610. /* alpha_num[mp_tar[X]], */
  2611. /* alpha_num[mp_tar[Y]], */
  2612. /* alpha_num[mp_tar[Z]]); */
  2613. next_node = &ba_main_grid[mp_tar[X]]
  2614. [mp_tar[Y]]
  2615. [mp_tar[Z]];
  2616. next_switch = &next_node->axis_switch[X];
  2617. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2618. info("Algo(%d) found %d looking at %c%c%c "
  2619. "going to %c%c%c %d",
  2620. algo, found,
  2621. alpha_num[ba_node->coord[X]],
  2622. alpha_num[ba_node->coord[Y]],
  2623. alpha_num[ba_node->coord[Z]],
  2624. alpha_num[mp_tar[X]],
  2625. alpha_num[mp_tar[Y]],
  2626. alpha_num[mp_tar[Z]],
  2627. port_tar);
  2628. list_append(results, next_node);
  2629. found++;
  2630. if (_find_x_path(results, next_node,
  2631. start, x_size, found,
  2632. conn_type, algo)) {
  2633. return 1;
  2634. } else {
  2635. found--;
  2636. _reset_the_path(curr_switch, 0, 1, X);
  2637. _remove_node(results, next_node->coord);
  2638. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2639. info("Algo(%d) couldn't finish "
  2640. "the path off this one", algo);
  2641. }
  2642. }
  2643. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2644. info("Algo(%d) couldn't find path", algo);
  2645. return 0;
  2646. }
  2647. error("We got here meaning there is a bad algo, "
  2648. "but this should never happen algo(%d)", algo);
  2649. return 0;
  2650. }
  2651. static int _remove_node(List results, uint16_t *mp_tar)
  2652. {
  2653. ListIterator itr;
  2654. ba_mp_t *ba_node = NULL;
  2655. itr = list_iterator_create(results);
  2656. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  2657. #ifdef HAVE_BG_L_P
  2658. if (mp_tar[X] == ba_node->coord[X]
  2659. && mp_tar[Y] == ba_node->coord[Y]
  2660. && mp_tar[Z] == ba_node->coord[Z]) {
  2661. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2662. info("removing %c%c%c from list",
  2663. alpha_num[mp_tar[X]],
  2664. alpha_num[mp_tar[Y]],
  2665. alpha_num[mp_tar[Z]]);
  2666. list_remove (itr);
  2667. break;
  2668. }
  2669. #else
  2670. if (mp_tar[X] == ba_node->coord[X]) {
  2671. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2672. info("removing %d from list",
  2673. mp_tar[X]);
  2674. list_remove (itr);
  2675. break;
  2676. }
  2677. #endif
  2678. }
  2679. list_iterator_destroy(itr);
  2680. return 1;
  2681. }
  2682. static int _find_next_free_using_port_2(ba_switch_t *curr_switch,
  2683. int source_port,
  2684. List nodes,
  2685. int dim,
  2686. int count)
  2687. {
  2688. ba_switch_t *next_switch = NULL;
  2689. ba_path_switch_t *path_add =
  2690. (ba_path_switch_t *) xmalloc(sizeof(ba_path_switch_t));
  2691. ba_path_switch_t *path_switch = NULL;
  2692. ba_path_switch_t *temp_switch = NULL;
  2693. uint16_t port_tar;
  2694. int target_port = 0;
  2695. int port_to_try = 2;
  2696. uint16_t *mp_tar= curr_switch->ext_wire[0].mp_tar;
  2697. uint16_t *node_src = curr_switch->ext_wire[0].mp_tar;
  2698. int used = 0;
  2699. int broke = 0;
  2700. ba_mp_t *ba_node = NULL;
  2701. ListIterator itr;
  2702. path_add->geometry[X] = node_src[X];
  2703. #ifdef HAVE_3D
  2704. path_add->geometry[Y] = node_src[Y];
  2705. path_add->geometry[Z] = node_src[Z];
  2706. #endif
  2707. path_add->dim = dim;
  2708. path_add->in = source_port;
  2709. if (count>=best_count)
  2710. goto return_0;
  2711. itr = list_iterator_create(nodes);
  2712. while ((ba_node = (ba_mp_t*) list_next(itr))) {
  2713. if (mp_tar[X] == ba_node->coord[X]
  2714. && mp_tar[Y] == ba_node->coord[Y]
  2715. && mp_tar[Z] == ba_node->coord[Z]) {
  2716. broke = 1;
  2717. break;
  2718. }
  2719. }
  2720. list_iterator_destroy(itr);
  2721. if (!broke && count>0 &&
  2722. !ba_main_grid[mp_tar[X]][mp_tar[Y]][mp_tar[Z]].used) {
  2723. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2724. info("this one not found %c%c%c",
  2725. alpha_num[mp_tar[X]],
  2726. alpha_num[mp_tar[Y]],
  2727. alpha_num[mp_tar[Z]]);
  2728. broke = 0;
  2729. if ((source_port%2))
  2730. target_port=1;
  2731. list_flush(best_path);
  2732. path_add->out = target_port;
  2733. list_push(path, path_add);
  2734. itr = list_iterator_create(path);
  2735. while ((path_switch = (ba_path_switch_t*) list_next(itr))){
  2736. temp_switch = (ba_path_switch_t *)
  2737. xmalloc(sizeof(ba_path_switch_t));
  2738. temp_switch->geometry[X] = path_switch->geometry[X];
  2739. temp_switch->geometry[Y] = path_switch->geometry[Y];
  2740. temp_switch->geometry[Z] = path_switch->geometry[Z];
  2741. temp_switch->dim = path_switch->dim;
  2742. temp_switch->in = path_switch->in;
  2743. temp_switch->out = path_switch->out;
  2744. list_append(best_path, temp_switch);
  2745. }
  2746. list_iterator_destroy(itr);
  2747. best_count = count;
  2748. return 1;
  2749. }
  2750. used=0;
  2751. if (!curr_switch->int_wire[port_to_try].used) {
  2752. itr = list_iterator_create(path);
  2753. while ((path_switch =
  2754. (ba_path_switch_t*) list_next(itr))){
  2755. if (((path_switch->geometry[X] == node_src[X])
  2756. && (path_switch->geometry[Y] == node_src[Y])
  2757. && (path_switch->geometry[Z] == mp_tar[Z]))) {
  2758. if ( path_switch->out
  2759. == port_to_try) {
  2760. used = 1;
  2761. break;
  2762. }
  2763. }
  2764. }
  2765. list_iterator_destroy(itr);
  2766. /* check to see if wire 0 is used with this port */
  2767. if (curr_switch->
  2768. ext_wire[port_to_try].mp_tar[X]
  2769. == curr_switch->ext_wire[0].mp_tar[X]
  2770. && curr_switch->ext_wire[port_to_try].mp_tar[Y]
  2771. == curr_switch->ext_wire[0].mp_tar[Y]
  2772. && curr_switch->ext_wire[port_to_try].mp_tar[Z]
  2773. == curr_switch->ext_wire[0].mp_tar[Z]) {
  2774. used = 1;
  2775. }
  2776. if (!used) {
  2777. port_tar = curr_switch->
  2778. ext_wire[port_to_try].port_tar;
  2779. mp_tar = curr_switch->
  2780. ext_wire[port_to_try].mp_tar;
  2781. next_switch = &ba_main_grid
  2782. [mp_tar[X]][mp_tar[Y]][mp_tar[Z]]
  2783. .axis_switch[X];
  2784. count++;
  2785. path_add->out = port_to_try;
  2786. list_push(path, path_add);
  2787. _find_next_free_using_port_2(next_switch,
  2788. port_tar, nodes,
  2789. dim, count);
  2790. while ((temp_switch = list_pop(path)) != path_add){
  2791. xfree(temp_switch);
  2792. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2793. info("something here 1");
  2794. }
  2795. }
  2796. }
  2797. return_0:
  2798. xfree(path_add);
  2799. return 0;
  2800. }
  2801. /*
  2802. * Used to tie the end of the block to the start. best_path and path
  2803. * should both be set up before calling this function.
  2804. *
  2805. * IN: curr_switch -
  2806. * IN: source_port -
  2807. * IN: dim -
  2808. * IN: count -
  2809. * IN: start -
  2810. *
  2811. * RET: 0 on failure, 1 on success
  2812. *
  2813. * Sets up global variable best_path, and best_count. On success
  2814. * best_count will be >= BEST_COUNT_INIT you can call _set_best_path
  2815. * to apply this path to the main system (ba_main_grid)
  2816. */
  2817. static int _finish_torus(List results,
  2818. ba_switch_t *curr_switch, int source_port,
  2819. int dim, int count, uint16_t *start)
  2820. {
  2821. ba_switch_t *next_switch = NULL;
  2822. ba_path_switch_t *path_add = xmalloc(sizeof(ba_path_switch_t));
  2823. ba_path_switch_t *path_switch = NULL;
  2824. ba_path_switch_t *temp_switch = NULL;
  2825. uint16_t port_tar;
  2826. int target_port=0;
  2827. int ports_to_try[2] = {3,5};
  2828. uint16_t *mp_tar= curr_switch->ext_wire[0].mp_tar;
  2829. uint16_t *node_src = curr_switch->ext_wire[0].mp_tar;
  2830. int i;
  2831. int used=0;
  2832. ListIterator itr;
  2833. path_add->geometry[X] = node_src[X];
  2834. path_add->geometry[Y] = node_src[Y];
  2835. path_add->geometry[Z] = node_src[Z];
  2836. path_add->dim = dim;
  2837. path_add->in = source_port;
  2838. if (count>=best_count) {
  2839. xfree(path_add);
  2840. return 0;
  2841. }
  2842. if (mp_tar[X] == start[X]
  2843. && mp_tar[Y] == start[Y]
  2844. && mp_tar[Z] == start[Z]) {
  2845. if ((source_port%2))
  2846. target_port=1;
  2847. if (!curr_switch->int_wire[target_port].used) {
  2848. list_flush(best_path);
  2849. path_add->out = target_port;
  2850. list_push(path, path_add);
  2851. itr = list_iterator_create(path);
  2852. while ((path_switch = list_next(itr))) {
  2853. temp_switch = xmalloc(sizeof(ba_path_switch_t));
  2854. temp_switch->geometry[X] =
  2855. path_switch->geometry[X];
  2856. temp_switch->geometry[Y] =
  2857. path_switch->geometry[Y];
  2858. temp_switch->geometry[Z] =
  2859. path_switch->geometry[Z];
  2860. temp_switch->dim = path_switch->dim;
  2861. temp_switch->in = path_switch->in;
  2862. temp_switch->out = path_switch->out;
  2863. list_append(best_path,temp_switch);
  2864. }
  2865. list_iterator_destroy(itr);
  2866. best_count = count;
  2867. return 1;
  2868. }
  2869. }
  2870. if (source_port==0 || source_port==3 || source_port==5) {
  2871. ports_to_try[0] = 4;
  2872. ports_to_try[1] = 2;
  2873. }
  2874. for(i=0;i<2;i++) {
  2875. used=0;
  2876. if (!curr_switch->int_wire[ports_to_try[i]].used) {
  2877. itr = list_iterator_create(path);
  2878. while ((path_switch = list_next(itr))){
  2879. if (((path_switch->geometry[X] == node_src[X])
  2880. && (path_switch->geometry[Y]
  2881. == node_src[Y])
  2882. && (path_switch->geometry[Z]
  2883. == mp_tar[Z]))) {
  2884. if ( path_switch->out
  2885. == ports_to_try[i]) {
  2886. used = 1;
  2887. break;
  2888. }
  2889. }
  2890. }
  2891. list_iterator_destroy(itr);
  2892. /* check to see if wire 0 is used with this port */
  2893. if ((curr_switch->
  2894. ext_wire[ports_to_try[i]].mp_tar[X] ==
  2895. curr_switch->ext_wire[0].mp_tar[X] &&
  2896. curr_switch->
  2897. ext_wire[ports_to_try[i]].mp_tar[Y] ==
  2898. curr_switch->ext_wire[0].mp_tar[Y] &&
  2899. curr_switch->
  2900. ext_wire[ports_to_try[i]].mp_tar[Z] ==
  2901. curr_switch->ext_wire[0].mp_tar[Z])) {
  2902. continue;
  2903. }
  2904. if (!used) {
  2905. ba_mp_t *next_node = NULL;
  2906. port_tar = curr_switch->
  2907. ext_wire[ports_to_try[i]].port_tar;
  2908. mp_tar = curr_switch->
  2909. ext_wire[ports_to_try[i]].mp_tar;
  2910. /* Check to see if I am going to a place I have
  2911. already been before, because even
  2912. though we may be able to do this
  2913. electrically this doesn't mean the
  2914. under lying infrastructure will
  2915. allow it. */
  2916. itr = list_iterator_create(results);
  2917. while ((next_node = list_next(itr))) {
  2918. if (ba_debug_flags
  2919. & DEBUG_FLAG_BG_ALGO_DEEP)
  2920. info("finishing_torus: "
  2921. "looking at %c%c%c "
  2922. "and %c%c%c",
  2923. alpha_num[next_node->
  2924. coord[X]],
  2925. alpha_num[next_node->
  2926. coord[Y]],
  2927. alpha_num[next_node->
  2928. coord[Z]],
  2929. alpha_num[mp_tar[X]],
  2930. alpha_num[mp_tar[Y]],
  2931. alpha_num[mp_tar[Z]]);
  2932. if ((mp_tar[X] == next_node->coord[X])
  2933. && (mp_tar[Y]
  2934. == next_node->coord[Y])
  2935. && (mp_tar[Z]
  2936. == next_node->coord[Z])) {
  2937. break;
  2938. }
  2939. }
  2940. list_iterator_destroy(itr);
  2941. if (next_node) {
  2942. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO)
  2943. info("finishing_torus: "
  2944. "Can't finish torus with "
  2945. "%c%c%c we already were "
  2946. "there.",
  2947. alpha_num[next_node->
  2948. coord[X]],
  2949. alpha_num[next_node->
  2950. coord[Y]],
  2951. alpha_num[next_node->
  2952. coord[Z]]);
  2953. continue;
  2954. }
  2955. next_switch = &ba_main_grid
  2956. [mp_tar[X]][mp_tar[Y]][mp_tar[Z]]
  2957. .axis_switch[dim];
  2958. count++;
  2959. path_add->out = ports_to_try[i];
  2960. list_push(path, path_add);
  2961. _finish_torus(results, next_switch, port_tar,
  2962. dim, count, start);
  2963. while ((temp_switch = list_pop(path))
  2964. != path_add){
  2965. xfree(temp_switch);
  2966. if (ba_debug_flags
  2967. & DEBUG_FLAG_BG_ALGO_DEEP)
  2968. info("something here 3");
  2969. }
  2970. }
  2971. }
  2972. }
  2973. xfree(path_add);
  2974. return 0;
  2975. }
  2976. /*
  2977. * using best_path set up previously from _finish_torus or
  2978. * _find_next_free_using_port_2. Will set up the path contained there
  2979. * into the main virtual system. With will also set the passthrough
  2980. * flag if there was a passthrough used.
  2981. */
  2982. static uint16_t *_set_best_path()
  2983. {
  2984. ListIterator itr;
  2985. ba_path_switch_t *path_switch = NULL;
  2986. ba_switch_t *curr_switch = NULL;
  2987. uint16_t *geo = NULL;
  2988. if (!best_path)
  2989. return NULL;
  2990. itr = list_iterator_create(best_path);
  2991. while ((path_switch = (ba_path_switch_t*) list_next(itr))) {
  2992. if (deny_pass && path_switch->in > 1 && path_switch->out > 1) {
  2993. *deny_pass |= PASS_FOUND_X;
  2994. debug2("got a passthrough in X");
  2995. }
  2996. if (ba_debug_flags & DEBUG_FLAG_BG_ALGO_DEEP)
  2997. info("mapping %c%c%c %d->%d",
  2998. alpha_num[path_switch->geometry[X]],
  2999. alpha_num[path_switch->geometry[Y]],
  3000. alpha_num[path_switch->geometry[Z]],
  3001. path_switch->in, path_switch->out);
  3002. if (!geo)
  3003. geo = path_switch->geometry;
  3004. curr_switch = &ba_main_grid
  3005. [path_switch->geometry[X]]
  3006. [path_switch->geometry[Y]]
  3007. [path_switch->geometry[Z]].
  3008. axis_switch[path_switch->dim];
  3009. curr_switch->int_wire[path_switch->in].used = 1;
  3010. curr_switch->int_wire[path_switch->in].port_tar =
  3011. path_switch->out;
  3012. curr_switch->int_wire[path_switch->out].used = 1;
  3013. curr_switch->int_wire[path_switch->out].port_tar =
  3014. path_switch->in;
  3015. }
  3016. list_iterator_destroy(itr);
  3017. best_count=BEST_COUNT_INIT;
  3018. return geo;
  3019. }
  3020. static int _set_one_dim(uint16_t *start, uint16_t *end, uint16_t *coord)
  3021. {
  3022. int dim;
  3023. ba_switch_t *curr_switch = NULL;
  3024. for(dim=0;dim<cluster_dims;dim++) {
  3025. if (start[dim]==end[dim]) {
  3026. curr_switch = &ba_main_grid
  3027. [coord[X]][coord[Y]][coord[Z]].axis_switch[dim];
  3028. if (!curr_switch->int_wire[0].used
  3029. && !curr_switch->int_wire[1].used) {
  3030. curr_switch->int_wire[0].used = 1;
  3031. curr_switch->int_wire[0].port_tar = 1;
  3032. curr_switch->int_wire[1].used = 1;
  3033. curr_switch->int_wire[1].port_tar = 0;
  3034. }
  3035. }
  3036. }
  3037. return 1;
  3038. }
  3039. static void _destroy_geo(void *object)
  3040. {
  3041. uint16_t *geo_ptr = (uint16_t *)object;
  3042. xfree(geo_ptr);
  3043. }