1 | import config.base
|
---|
2 | import os
|
---|
3 | import sys
|
---|
4 | import string
|
---|
5 |
|
---|
6 | class CacheAttribute(object):
|
---|
7 | def __init__(self, name, keyword, help, default=None, min=0, max=min(sys.maxint,2**31-1)):
|
---|
8 | self.name = name
|
---|
9 | self.help = help
|
---|
10 | self.keyword = keyword
|
---|
11 | self.default = default
|
---|
12 | self.min = min
|
---|
13 | self.max = max
|
---|
14 | def valid(self,val):
|
---|
15 | return self.min <= val <= self.max
|
---|
16 | def sanitize(self,val):
|
---|
17 | if self.valid(val):
|
---|
18 | return val
|
---|
19 | else:
|
---|
20 | return self.default
|
---|
21 | def enum(self):
|
---|
22 | return self.name.upper().replace('-','_')
|
---|
23 |
|
---|
24 | class Configure(config.base.Configure):
|
---|
25 | def __init__(self, framework):
|
---|
26 | config.base.Configure.__init__(self, framework)
|
---|
27 | self.headerPrefix = 'PETSC'
|
---|
28 | self.substPrefix = 'PETSC'
|
---|
29 | self.updated = 0
|
---|
30 | self.strmsg = ''
|
---|
31 | self.attrs = [CacheAttribute('level1-dcache-size', 'int', 'Size in bytes of Level 1 data cache', 32768, 16),
|
---|
32 | CacheAttribute('level1-dcache-linesize', 'int', 'Size in bytes of each line of the Level 1 data cache', 32, 16),
|
---|
33 | CacheAttribute('level1-dcache-assoc', 'int', 'Associativity of the Level 1 data cache, 0 for full associative', 2, 0)]
|
---|
34 | self.method = None
|
---|
35 | return
|
---|
36 |
|
---|
37 | def __str__(self):
|
---|
38 | return self.strmsg
|
---|
39 |
|
---|
40 | def setupHelp(self, help):
|
---|
41 | import nargs
|
---|
42 | for a in self.attrs:
|
---|
43 | help.addArgument('PETSc', '-known-'+a.name+'=<'+a.keyword+'>', nargs.ArgInt(None, None, a.help, min=a.min, max=a.max))
|
---|
44 | return
|
---|
45 |
|
---|
46 | def setupDependencies(self, framework):
|
---|
47 | config.base.Configure.setupDependencies(self, framework)
|
---|
48 | self.compilers = framework.require('config.compilers', self)
|
---|
49 | self.headers = framework.require('config.headers', self)
|
---|
50 | return
|
---|
51 |
|
---|
52 | def getconfFunction(self, a):
|
---|
53 | VAR = a.enum()
|
---|
54 | funcname = 'getconf_' + VAR
|
---|
55 | sanitize = '('+str(a.min)+' <= val && val <= '+str(a.max)+') ? val : '+str(a.default)
|
---|
56 | methods = [
|
---|
57 | # On some systems, maybe just with glibc, sysconf can provide this stuff
|
---|
58 | '#include <unistd.h>\nlong '+funcname+'() { long val = sysconf(_SC_'+VAR+'); return '+sanitize+'; }\n'
|
---|
59 | ,
|
---|
60 | # A total hack since this will compile with any C compiler, but only return useful results when the getconf program is available
|
---|
61 | '#include <stdio.h>\nlong '+funcname+'() { long val=-1; FILE *f = popen("getconf '+VAR+'","r"); fscanf(f,"%ld",&val); pclose(f); return '+sanitize+'; }\n'
|
---|
62 | ,
|
---|
63 | # Fallback that just returns the default, guaranteed to compile
|
---|
64 | 'long '+funcname+'() { return '+str(a.default)+'; }\n'
|
---|
65 | ]
|
---|
66 | if self.method is None: # Determine which method of finding configuration variables, only runs the first time around
|
---|
67 | self.pushLanguage('C')
|
---|
68 | for m in range(len(methods)):
|
---|
69 | d = methods[m]
|
---|
70 | if self.checkCompile(d,''):
|
---|
71 | self.method = m
|
---|
72 | break
|
---|
73 | self.popLanguage()
|
---|
74 | if self.method is None:
|
---|
75 | raise RuntimeError("The C compiler does not work")
|
---|
76 | return (funcname,methods[self.method])
|
---|
77 |
|
---|
78 | def configureCacheDetails(self):
|
---|
79 | '''Try to determine the size and associativity of the cache.'''
|
---|
80 | for a in self.attrs:
|
---|
81 | arg = 'known-' + a.name
|
---|
82 | (fname, source) = self.getconfFunction(a)
|
---|
83 | if arg in self.framework.argDB:
|
---|
84 | val = self.framework.argDB[arg]
|
---|
85 | elif self.framework.argDB['with-batch']:
|
---|
86 | body = 'freopen("/dev/null","w",stderr);\n' + 'fprintf(output," \'--'+arg+'=%ld\',\\n",'+fname+'());'
|
---|
87 | self.framework.addBatchInclude(source)
|
---|
88 | self.framework.addBatchBody(body)
|
---|
89 | val = a.default
|
---|
90 | else:
|
---|
91 | filename = 'conftestval'
|
---|
92 | includes = '#include <stdio.h>\n'
|
---|
93 | body = 'FILE *output = fopen("'+filename+'","w"); if (!output) return 1; fprintf(output,"%ld",'+fname+'()); fclose(output);'
|
---|
94 | self.pushLanguage('C')
|
---|
95 | if self.checkRun(includes+source, body) and os.path.exists(filename):
|
---|
96 | f = open(filename)
|
---|
97 | val = int(f.read())
|
---|
98 | if not a.valid(val):
|
---|
99 | self.framework.log.write('Cannot use value returned for '+str(a.enum())+': '+str(val)+'\n')
|
---|
100 | f.close()
|
---|
101 | else:
|
---|
102 | self.framework.log.write('Could not determine '+str(a.enum())+', using default '+str(a.default)+'\n')
|
---|
103 | val = a.default
|
---|
104 | self.popLanguage()
|
---|
105 | self.addDefine(a.enum(), a.sanitize(val))
|
---|
106 |
|
---|
107 | def configure(self):
|
---|
108 | self.executeTest(self.configureCacheDetails)
|
---|
109 | return
|
---|