/* * PCN System: Virtual topology library * Author: Robert Olson * Argonne National Laboratory * * Please see the DISCLAIMER file in the top level directory of the * distribution regarding the provisions under which this software * is distributed. * * vts.pcn - Basic VT functions for array, ring, and mesh topologies * */ -disable_function_calls() -directive("functions", "ring", "ring_fn", "array", "array_fn", "mesh", "mesh_fn", "north", "south", "east", "west", "fwd", "bwd", "node", "mesh_node") -metacalls(mesh, mesh_fn) -metacalls(ring, ring_fn) -metacalls(array, array_fn) -metacalls(north, south, east, west, fwd, bwd) -metacalls(node, mesh_node) ring(n) {? int(n) -> {; vt_lib:nodes(old_n), new_topo = ring(n), size = n, fn = {"call", {":", "vts", "ring_fn"}, [old_n], []}, retval = {new_topo, size, fn}, return(retval) }, default -> {|| stdio:printf("ring needs an integral argument\n",{},_) } } ring_fn(old_n, new) {|| retval = new % old_n, return(retval) } array(n) {? int(n) -> {; vt_lib:nodes(old_n), new_topo = array(n), size = n, fn = {"call", {":", "vts", "array_fn"}, [old_n], []}, retval = {new_topo, size, fn}, return(retval) }, default -> {|| stdio:printf("ring needs an integral argument\n",{},_) } } array_fn(old_n, new) {|| retval = new % old_n, return(retval) } mesh(m, n) {|| old_topo = topology(), {? old_topo ?= array(old_n) -> {; new_topo = mesh(m,n), size = m * n, fn = {"call", {":", "vts", "mesh_fn"}, [m, n, old_n], []}, retval = {new_topo, size, fn}, return(retval) }, default -> {|| stdio:printf("Cannot create a mesh from a non-array %t\n", {old_topo}, _) } } } mesh_fn(m, n, old_n, new) {|| old = new % old_n , return(old) } north() {? topology() ?= mesh(m,n) -> {|| there = (location() + n) % (m * n), return(there) }, default -> {|| stdio:printf("Error: relocation north not defined for non-mesh topology %t\n", {topology()}, _) } } south() {? topology() ?= mesh(m,n) -> {|| there = (location() - n + m * n) % (m * n), return(there) }, default -> {|| stdio:printf("Error: relocation south not defined for non-mesh topology %t\n", {topology()}, _) } } east() {? topology() ?= mesh(m,n) -> {; here_m = location() / n, here_n = location() % n, there_m = here_m, there_n = (here_n + 1) % n, there = there_m * n + there_n, return(there) }, default -> {|| stdio:printf("Error: relocation east not defined for non-mesh topology %t\n", {topology()}, _) } } west() {? topology() ?= mesh(m,n) -> {; here_m = location() / n, here_n = location() % n, there_m = here_m, there_n = (here_n - 1 + n) % n, there = there_m * n + there_n, return(there) }, default -> {|| stdio:printf("North not defined for non-mesh topology %t\n", {topology()}, _) } } fwd() {|| {? topology() ?= array(n) -> {? location() == n - 1 -> {|| stdio:printf("Error: bounds violation for relocation fwd in array location %d\n", {location()}, _) }, default -> {|| there = location() + 1 } }, topology() ?= ring(n) -> {|| there = (location() + 1) % n }, default -> {|| stdio:printf("Error: relocation fwd not defined for topology %t\n", {topology()},_) } }, return(there) } bwd() {|| {? topology() ?= array(n) -> {? location() == 0 -> {|| stdio:printf("Error: bounds violation for relocation bwd in array location %d\n", {location()}, _) }, default -> {|| there = location() - 1 } }, topology() ?= ring(n) -> {|| there = (location() - 1 + n) % n }, default -> {|| stdio:printf("Error: relocation bwd not defined for topology %t\n", {topology()},_) } }, return(there) } node(x) {? int(x), x >= 0, x < nodes() -> {|| return(x) }, default -> {|| vt_msg:warning("vts:node: Invalid relocation to %lt, mapping to node 0 instead", {x}), return(0) } } mesh_node(x, y) {? topology() ?= mesh(m,n) -> {? int(x), int(y), x >= 0, x < m, y >= 0, y < n -> {|| locn = x * n + y, return(locn) }, default -> {|| vt_msg:warning("vts:mesh_node: Invalid relocation to (%lt,%lt), mapping to node 0,0 instead", {x,y}), return(0) } }, default -> {|| vt_msg:error("mesh_node not defined for non-mesh topology %t", {topology()}) } }