From f29d99c8b39b8f8689d385e548a16e59e0982915 Mon Sep 17 00:00:00 2001
From: Rafael Ravedutti <rafaelravedutti@gmail.com>
Date: Thu, 17 Feb 2022 00:05:36 +0100
Subject: [PATCH] Add Target class

Signed-off-by: Rafael Ravedutti <rafaelravedutti@gmail.com>
---
 examples/lj_func.py          |  1 +
 src/pairs/__init__.py        |  7 +++++++
 src/pairs/code_gen/target.py | 39 ++++++++++++++++++++++++++++++++++++
 src/pairs/sim/simulation.py  | 13 ++++++++++--
 4 files changed, 58 insertions(+), 2 deletions(-)
 create mode 100644 src/pairs/code_gen/target.py

diff --git a/examples/lj_func.py b/examples/lj_func.py
index 97d7200..162d88d 100644
--- a/examples/lj_func.py
+++ b/examples/lj_func.py
@@ -31,4 +31,5 @@ psim.periodic(2.8)
 psim.vtk_output("output/test")
 psim.compute(lj, cutoff_radius, {'sigma6': sigma6, 'epsilon': epsilon})
 psim.compute(euler, symbols={'dt': dt})
+psim.target(pairs.target_gpu())
 psim.generate()
diff --git a/src/pairs/__init__.py b/src/pairs/__init__.py
index 98e050f..75615c3 100644
--- a/src/pairs/__init__.py
+++ b/src/pairs/__init__.py
@@ -1,6 +1,13 @@
 from pairs.code_gen.cgen import CGen
+from pairs.code_gen.target import Target
 from pairs.sim.simulation import Simulation
 
 
 def simulation(ref, dims=3, timesteps=100, debug=False):
     return Simulation(CGen(f"{ref}.cpp", debug), dims, timesteps)
+
+def target_cpu():
+    return Target(Target.Backend_CPP, Target.Feature_CPU)
+
+def target_gpu():
+    return Target(Target.Backend_CUDA, Target.Feature_GPU)
diff --git a/src/pairs/code_gen/target.py b/src/pairs/code_gen/target.py
new file mode 100644
index 0000000..30acef5
--- /dev/null
+++ b/src/pairs/code_gen/target.py
@@ -0,0 +1,39 @@
+class Target:
+    # Architectures
+    Arch_x86 = 0
+    Arch_Nvidia = 1
+
+    # Backend
+    Backend_CPP = 0
+    Backend_CUDA = 1
+    Backend_LLVM = 2
+
+    # Features
+    Feature_CPU = 1
+    Feature_AVX = 2
+    Feature_AVX2 = 3
+    Feature_AVX512 = 4
+    Feature_GPU = 5
+
+    # Operating system
+    OS_Unknown = 0
+    OS_Linux = 1
+    OS_Windows = 2
+
+    def __init__(self, backend, features, arch=None, os=None):
+        self.backend = backend
+        self.features = features if isinstance(features, list) else [features]
+        self.arch = arch if arch is not None else Target.Arch_x86 if Target.Feature_CPU in self.features else Target.Arch_Nvidia
+        self.os = os if os is not None else Target.OS_Unknown
+
+    def add_feature(self, feature):
+        self.features.append(feature)
+
+    def has_feature(self, feature):
+        return feature in self.features
+
+    def is_cpu(self):
+        return self.has_feature(Target.Feature_CPU)
+
+    def is_gpu(self):
+        return self.has_feature(Target.Feature_GPU)
diff --git a/src/pairs/sim/simulation.py b/src/pairs/sim/simulation.py
index ba8e8f7..5aa9c4c 100644
--- a/src/pairs/sim/simulation.py
+++ b/src/pairs/sim/simulation.py
@@ -63,6 +63,7 @@ class Simulation:
         self.expr_id = 0
         self.iter_id = 0
         self.vtk_file = None
+        self._target = None
         self.nparticles = self.nlocal + self.nghost
         self.properties.add_capacity(self.particle_capacity)
 
@@ -214,7 +215,12 @@ class Simulation:
     def vtk_output(self, filename):
         self.vtk_file = filename
 
+    def target(self, target):
+        self._target = target
+
     def generate(self):
+        assert self._target is not None, "Target not specified!"
+
         timestep = Timestep(self, self.ntimesteps, [
             (EnforcePBC(self, self.pbc), 20),
             (SetupPBC(self, self.pbc), UpdatePBC(self, self.pbc), 20),
@@ -242,7 +248,8 @@ class Simulation:
         ])
 
         program = Module(self, name='main', block=Block.merge_blocks(decls, body))
-        add_copies = AddDeviceCopies(program)
+        if self._target.is_gpu():
+            add_copies = AddDeviceCopies(program)
 
         # Transformations
         lower_everything(program)
@@ -254,7 +261,9 @@ class Simulation:
         set_used_bin_ops(program)
         modularize(program)
         merge_adjacent_blocks(program)
-        add_copies.mutate()
+
+        if self._target.is_gpu():
+            add_copies.mutate()
 
         # For this part on, all bin ops are generated without usage verification
         self.check_decl_usage = False
-- 
GitLab