static void core_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; unsigned myheight = (fontsize ? (fontsize + gridsize) : 0), totheight; unsigned mywidth = 0, totwidth; unsigned textwidth = gridsize; char text[64]; int n; struct style style; DYNA_CHECK(); if (fontsize) { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(loutput, methods, text, n, fontsize, gridsize); } RECURSE_RECT(level, &null_draw_methods, 0, gridsize); lstopo_set_object_color(methods, topology, level, 0, &style); methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, totwidth, y, totheight); if (fontsize) { methods->text(loutput, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + gridsize, text); } RECURSE_RECT(level, methods, 0, gridsize); DYNA_SAVE(); }
static void cache_draw(hwloc_topology_t topology, struct draw_methods *methods, int logical, hwloc_obj_t level, void *output, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { unsigned myheight = gridsize + (fontsize ? (fontsize + gridsize) : 0) + gridsize, totheight; unsigned mywidth = 0, totwidth; unsigned textwidth = gridsize; /* Do not separate objects when in L1 (SMT) */ unsigned separator = level->attr->cache.depth > 1 ? gridsize : 0; char text[64]; int n; struct style style; DYNA_CHECK(); if (fontsize) { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(output, methods, text, n, fontsize, gridsize); textwidth += gridsize; /* artificially extend the minimal inner size because RECURSE_RECT() uses 0 as border when computing totwidth */ } RECURSE_RECT(level, &null_draw_methods, separator, 0); lstopo_set_object_color(methods, topology, level, 0, &style); methods->box(output, style.bg.r, style.bg.g, style.bg.b, depth, x, totwidth, y, myheight - gridsize); if (fontsize) { methods->text(output, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + gridsize, text); } RECURSE_RECT(level, methods, separator, 0); DYNA_SAVE(); }
static void pci_device_draw(hwloc_topology_t topology __hwloc_attribute_unused, struct draw_methods *methods, int logical, hwloc_obj_t level, void *output, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { unsigned textwidth = gridsize; unsigned textheight = (fontsize ? fontsize + gridsize : 0); unsigned myheight = textheight; unsigned mywidth = 0; unsigned totwidth, totheight; unsigned overlaidoffset = 0; struct style style; char text[64], _text[64]; const char *collapsestr = hwloc_obj_get_info_by_name(level, "lstopoCollapse"); unsigned collapse = collapsestr ? atoi(collapsestr) : 1; int n; DYNA_CHECK(); if (fontsize) { if (collapse > 1) { n = lstopo_obj_snprintf(_text, sizeof(_text), level, logical); n = snprintf(text, sizeof(text), "%u x { %s }", collapse, _text); } else { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); } textwidth = get_textwidth(output, methods, text, n, fontsize, gridsize); } if (collapse > 1) { /* additional depths and height for overlaid boxes */ depth -= 2; if (collapse > 2) { overlaidoffset = gridsize; } else { overlaidoffset = gridsize/2; } textwidth += overlaidoffset; textheight += overlaidoffset; myheight = textheight; } RECURSE_RECT(level, &null_draw_methods, gridsize, gridsize); lstopo_set_object_color(methods, topology, level, 0, &style); if (collapse > 1) { methods->box(output, style.bg.r, style.bg.g, style.bg.b, depth+2, x + overlaidoffset, *retwidth - overlaidoffset, y + overlaidoffset, *retheight - overlaidoffset); if (collapse > 2) methods->box(output, style.bg.r, style.bg.g, style.bg.b, depth+1, x + overlaidoffset/2, *retwidth - overlaidoffset, y + overlaidoffset/2, *retheight - overlaidoffset); methods->box(output, style.bg.r, style.bg.g, style.bg.b, depth, x, *retwidth - overlaidoffset, y, *retheight - overlaidoffset); } else { methods->box(output, style.bg.r, style.bg.g, style.bg.b, depth, x, *retwidth, y, *retheight); } if (fontsize) methods->text(output, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + gridsize, text); RECURSE_RECT(level, methods, gridsize, gridsize); DYNA_SAVE(); }
static void pu_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; unsigned myheight = (fontsize ? (fontsize + gridsize) : 0), totheight; unsigned textwidth = gridsize; unsigned mywidth = 0, totwidth; unsigned textxoffset = 0; char text[64]; int n; struct style style; int colorarg; DYNA_CHECK(); if (fontsize) { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(loutput, methods, text, n, fontsize, gridsize); /* if smaller than other PU, artificially extend/shift it * to make PU boxes nicer when vertically stacked. */ if (textwidth < loutput->min_pu_textwidth) { textxoffset = (loutput->min_pu_textwidth - textwidth) / 2; textwidth = loutput->min_pu_textwidth; } } RECURSE_RECT(level, &null_draw_methods, 0, gridsize); if (lstopo_pu_forbidden(level)) colorarg = 2; else if (lstopo_pu_running(loutput, level)) colorarg = 1; else colorarg = 0; lstopo_set_object_color(methods, topology, level, colorarg, &style); methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, *retwidth, y, *retheight); if (fontsize) { methods->text(loutput, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize + textxoffset, y + gridsize, text); } RECURSE_RECT(level, methods, 0, gridsize); DYNA_SAVE(); }
static void node_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; /* Reserve room for the heading memory box and separator */ unsigned myheight = (fontsize ? (gridsize + fontsize) : 0) + gridsize + gridsize; /* Currently filled height */ unsigned totheight; /* Nothing on the left */ unsigned mywidth = 0; /* Currently filled width */ unsigned totwidth; /* Width of the heading text, thus minimal width */ unsigned textwidth = gridsize; char text[64]; int n; struct style style; /* Check whether dynamic programming can save us time */ DYNA_CHECK(); if (fontsize) { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(loutput, methods, text, n, fontsize, gridsize); textwidth += 2*gridsize; /* so artificially extend the minimal inner size to include space between space between epoxy and memory box */ } /* Compute the size needed by sublevels */ RECURSE_RECT(level, &null_draw_methods, gridsize, gridsize); lstopo_set_object_color(methods, topology, level, 0 /* node */, &style); /* Draw the epoxy box */ methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, totwidth, y, totheight); /* Draw the memory box */ methods->box(loutput, style.bg2.r, style.bg2.g, style.bg2.b, depth-1, x + gridsize, totwidth - 2 * gridsize, y + gridsize, myheight - gridsize); if (fontsize) { methods->text(loutput, style.t2.r, style.t2.g, style.t2.b, fontsize, depth-2, x + 2 * gridsize, y + 2 * gridsize, text); } /* Restart, now really drawing sublevels */ RECURSE_RECT(level, methods, gridsize, gridsize); /* Save result for dynamic programming */ DYNA_SAVE(); }
static void group_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; unsigned myheight = (fontsize ? (fontsize + gridsize) : 0), totheight; unsigned mywidth = 0, totwidth; unsigned textwidth = gridsize; int vert = prefer_vert(loutput, level, depth, x, y, gridsize); char text[64]; int n; struct style style; DYNA_CHECK(); if (fontsize) { n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(loutput, methods, text, n, fontsize, gridsize); } if (level->arity > 1 && (level->children[0]->type == HWLOC_OBJ_MACHINE || !level->children[0]->cpuset)) NETWORK_DRAW_BEGIN(); else RECURSE_RECT(level, &null_draw_methods, gridsize, gridsize); lstopo_set_object_color(methods, topology, level, 0, &style); methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, totwidth, y, totheight); if (fontsize) { methods->text(loutput, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + gridsize, text); } if (level->arity > 1 && (level->children[0]->type == HWLOC_OBJ_MACHINE || !level->children[0]->cpuset)) NETWORK_DRAW_END(); else RECURSE_RECT(level, methods, gridsize, gridsize); DYNA_SAVE(); }
static void bridge_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; unsigned textwidth = 0; unsigned myheight = 0; /* Room for square, left link and speed */ unsigned speedwidth = fontsize ? fontsize + gridsize : 0; unsigned mywidth = 2*gridsize + gridsize + speedwidth; unsigned totwidth, totheight; struct style style; unsigned center; DYNA_CHECK(); RECURSE_VERT(level, &null_draw_methods, gridsize, 0); /* Square and left link */ lstopo_set_object_color(methods, topology, level, 0, &style); methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, gridsize, y + PCI_HEIGHT/2 - gridsize/2, gridsize); methods->line(loutput, 0, 0, 0, depth, x + gridsize, y + PCI_HEIGHT/2, x + 2*gridsize, y + PCI_HEIGHT/2); if (level->io_arity > 0) { unsigned bottom = 0, top = 0; RECURSE_BEGIN(level, 0); RECURSE_FOR(level) RECURSE_CALL_FUN(methods); /* Line to PCI device */ center = y + totheight + PCI_HEIGHT / 2; if (!top) top = center; bottom = center; methods->line(loutput, 0, 0, 0, depth, x + 2*gridsize, center, x + 2*gridsize + gridsize + speedwidth, center); /* Negotiated link speed */ if (fontsize) { float speed = 0.; if (child->type == HWLOC_OBJ_PCI_DEVICE) speed = child->attr->pcidev.linkspeed; if (child->type == HWLOC_OBJ_BRIDGE && child->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) speed = child->attr->bridge.upstream.pci.linkspeed; if (speed != 0.) { char text[4]; if (speed >= 10.) snprintf(text, sizeof(text), "%.0f", child->attr->pcidev.linkspeed); else snprintf(text, sizeof(text), "%0.1f", child->attr->pcidev.linkspeed); methods->text(loutput, style.t2.r, style.t2.g, style.t2.b, fontsize, depth-1, x + 2*gridsize + gridsize, y + totheight, text); } } RECURSE_END_VERT(gridsize, 0); /* Vertical line */ methods->line(loutput, 0, 0, 0, depth, x + 2*gridsize, top, x + 2*gridsize, bottom); } else RECURSE_VERT(level, methods, gridsize, 0); /* Empty bridges still need some room */ if (*retheight < PCI_HEIGHT) *retheight = PCI_HEIGHT; DYNA_SAVE(); }
static void os_device_draw(struct lstopo_output *loutput, struct draw_methods *methods, hwloc_obj_t level, unsigned depth, unsigned x, unsigned *retwidth, unsigned y, unsigned *retheight) { hwloc_topology_t topology = loutput->topology; int logical = loutput->logical; unsigned gridsize = loutput->gridsize; unsigned fontsize = loutput->fontsize; unsigned myheight = 0, totheight; unsigned mywidth = 0, totwidth; unsigned textwidth = gridsize; struct style style; char text[64]; int n; unsigned nmorelines = 0, i; char morelines[3][64]; DYNA_CHECK(); if (fontsize) { const char *coproctype = level->subtype; if (HWLOC_OBJ_OSDEV_COPROC == level->attr->osdev.type && coproctype) { if (!strcmp(coproctype, "CUDA")) { const char *value, *value2, *value3; value = hwloc_obj_get_info_by_name(level, "CUDAGlobalMemorySize"); if (value) { unsigned long long mb = strtoull(value, NULL, 10) / 1024; snprintf(morelines[nmorelines], sizeof(morelines[0]), mb >= 10240 ? "%llu GB" : "%llu MB", mb >= 10240 ? mb/1024 : mb); nmorelines++; } value = hwloc_obj_get_info_by_name(level, "CUDAL2CacheSize"); if (value) { unsigned long long kb = strtoull(value, NULL, 10); snprintf(morelines[nmorelines], sizeof(morelines[0]), kb >= 10240 ? "L2 (%llu MB)" : "L2 (%llu kB)", kb >= 10240 ? kb/1024 : kb); nmorelines++; } value = hwloc_obj_get_info_by_name(level, "CUDAMultiProcessors"); value2 = hwloc_obj_get_info_by_name(level, "CUDACoresPerMP"); value3 = hwloc_obj_get_info_by_name(level, "CUDASharedMemorySizePerMP"); if (value && value2 && value3) { snprintf(morelines[nmorelines], sizeof(morelines[0]), "%s MP x (%s cores + %s kB)", value, value2, value3); nmorelines++; } } else if (!strcmp(coproctype, "MIC")) { const char *value; value = hwloc_obj_get_info_by_name(level, "MICActiveCores"); if (value) { snprintf(morelines[nmorelines], sizeof(morelines[0]), "%s cores", value); nmorelines++; } value = hwloc_obj_get_info_by_name(level, "MICMemorySize"); if (value) { unsigned long long mb = strtoull(value, NULL, 10) / 1024; snprintf(morelines[nmorelines], sizeof(morelines[0]), mb >= 10240 ? "%llu GB" : "%llu MB", mb >= 10240 ? mb/1024 : mb); nmorelines++; } } else if (!strcmp(coproctype, "OpenCL")) { const char *value; value = hwloc_obj_get_info_by_name(level, "OpenCLComputeUnits"); if (value) { unsigned long long cu = strtoull(value, NULL, 10); snprintf(morelines[nmorelines], sizeof(morelines[0]), "%llu compute units", cu); nmorelines++; } value = hwloc_obj_get_info_by_name(level, "OpenCLGlobalMemorySize"); if (value) { unsigned long long mb = strtoull(value, NULL, 10) / 1024; snprintf(morelines[nmorelines], sizeof(morelines[0]), mb >= 10240 ? "%llu GB" : "%llu MB", mb >= 10240 ? mb/1024 : mb); nmorelines++; } } } else if (HWLOC_OBJ_OSDEV_BLOCK == level->attr->osdev.type) { const char *value; value = hwloc_obj_get_info_by_name(level, "Size"); if (value) { unsigned long long mb = strtoull(value, NULL, 10) / 1024; snprintf(morelines[nmorelines], sizeof(morelines[0]), mb >= 10485760 ? "%llu TB" : mb >= 10240 ? "%llu GB" : "%llu MB", mb >= 10485760 ? mb/1048576 : mb >= 10240 ? mb/1024 : mb); nmorelines++; } } n = lstopo_obj_snprintf(text, sizeof(text), level, logical); textwidth = get_textwidth(loutput, methods, text, n, fontsize, gridsize); for(i=0; i<nmorelines; i++) { unsigned nn = (unsigned)strlen(morelines[i]); unsigned ntextwidth = get_textwidth(loutput, methods, morelines[i], nn, fontsize, gridsize); if (ntextwidth > textwidth) textwidth = ntextwidth; } myheight = (fontsize + gridsize)*(nmorelines+1); mywidth = 0; } RECURSE_RECT(level, &null_draw_methods, gridsize, gridsize); lstopo_set_object_color(methods, topology, level, 0, &style); methods->box(loutput, style.bg.r, style.bg.g, style.bg.b, depth, x, *retwidth, y, *retheight); if (fontsize) { methods->text(loutput, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + gridsize, text); for(i=0; i<nmorelines; i++) methods->text(loutput, style.t.r, style.t.g, style.t.b, fontsize, depth-1, x + gridsize, y + (i+2)*gridsize + (i+1)*fontsize, morelines[i]); } RECURSE_RECT(level, methods, gridsize, gridsize); DYNA_SAVE(); }