configs: allow fs.py and fs_bigLITTLE.py to work without M5_PATH

The requirement to have an environment variable exported to run a program
is not common, and many new users trip up on it.

Before this commit, M5_PATH was a requirement to run those scripts, or
else simulation would fail with:

IOError: Can't find a path to system files.

After this patch, as long as users indicate all required files with
command line options, M5_PATH is not needed.

This patch changes the M5_PATH semantics slightly to more closely match
PATH and so be more intuitive to users: after this commit, if the
given path contains a slash /, then the path is not searched for inside
M5_PATH, which is exactly how PATH works. Users can then select images
in the CWD with a leading ./ just as done for executables.

This is backwards incompatible if users were already specifying their paths
as ./, but this interface feels saner, because otherwise writing on the CLI
e.g.:

--disk-image path/to/my.disk

would previously fail to find the disk, even if it existed, which is very
counter-intuitive. The following will still fail however:

--disk-image my.disk

which is not ideal, but for now is a comprise between backwards
compatibility of having an M5_PATH and what users expect from CLI
interfaces.

Change-Id: Ic91e1cc20557b35b69490b6dc420e7d324fae1fc
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/23672
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/configs/common/SysPaths.py b/configs/common/SysPaths.py
index e5d9f83..0a67789 100644
--- a/configs/common/SysPaths.py
+++ b/configs/common/SysPaths.py
@@ -37,6 +37,7 @@
 
 class PathSearchFunc(object):
     _sys_paths = None
+    environment_variable = 'M5_PATH'
 
     def __init__(self, subdirs, sys_paths=None):
         if isinstance(subdirs, string_types):
@@ -46,29 +47,36 @@
             self._sys_paths = sys_paths
 
     def __call__(self, filename):
-        if self._sys_paths is None:
+        if os.sep in filename:
+            return filename
+        else:
+            if self._sys_paths is None:
+                try:
+                    paths = os.environ[self.environment_variable].split(':')
+                except KeyError:
+                    paths = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ]
+
+                # expand '~' and '~user' in paths
+                paths = map(os.path.expanduser, paths)
+
+                # filter out non-existent directories
+                paths = filter(os.path.isdir, paths)
+
+                if not paths:
+                    raise IOError(
+                        "Can't find system files directory, "
+                        "check your {} environment variable"
+                        .format(self.environment_variable))
+
+                self._sys_paths = list(paths)
+
+            filepath = os.path.join(self._subdir, filename)
+            paths = (os.path.join(p, filepath) for p in self._sys_paths)
             try:
-                paths = os.environ['M5_PATH'].split(':')
-            except KeyError:
-                paths = [ '/dist/m5/system', '/n/poolfs/z/dist/m5/system' ]
-
-            # expand '~' and '~user' in paths
-            paths = map(os.path.expanduser, paths)
-
-            # filter out non-existent directories
-            paths = filter(os.path.isdir, paths)
-
-            if not paths:
-                raise IOError("Can't find a path to system files.")
-
-            self._sys_paths = list(paths)
-
-        filepath = os.path.join(self._subdir, filename)
-        paths = (os.path.join(p, filepath) for p in self._sys_paths)
-        try:
-            return next(p for p in paths if os.path.exists(p))
-        except StopIteration:
-            raise IOError("Can't find file '%s' on path." % filename)
+                return next(p for p in paths if os.path.exists(p))
+            except StopIteration:
+                raise IOError("Can't find file '{}' on {}."
+                        .format(filename, self.environment_variable))
 
 disk = PathSearchFunc('disks')
 binary = PathSearchFunc('binaries')