+class Checker(object):
+ def __init__(self, ref, test, tag):
+ self.ref = ref
+ self.test = test
+ self.tag = tag
+
+ def check(self):
+ with open(self.test) as test_f, open(self.ref) as ref_f:
+ return test_f.read() == ref_f.read()
+
+def tagged_filt(tag, num):
+ return (r'\n{}: \({}{}\) .*\n(In file: .*\n)?'
+ r'(In process: [\w.]* @ .*\n)?').format(tag, tag[0], num)
+
+def error_filt(num):
+ return tagged_filt('Error', num)
+
+def warning_filt(num):
+ return tagged_filt('Warning', num)
+
+def info_filt(num):
+ return tagged_filt('Info', num)
+
+class DiffingChecker(Checker):
+ def __init__(self, ref, test, tag, out_dir):
+ super(DiffingChecker, self).__init__(ref, test, tag)
+ self.out_dir = out_dir
+
+ def diffing_check(self, ref_lines, test_lines):
+ test_file = os.path.basename(self.test)
+ ref_file = os.path.basename(self.ref)
+
+ diff_file = '.'.join([ref_file, 'diff'])
+ diff_path = os.path.join(self.out_dir, diff_file)
+ if test_lines != ref_lines:
+ with open(diff_path, 'w') as diff_f:
+ for line in difflib.unified_diff(
+ ref_lines, test_lines,
+ fromfile=ref_file,
+ tofile=test_file):
+ diff_f.write(line)
+ return False
+ else:
+ if os.path.exists(diff_path):
+ os.unlink(diff_path)
+ return True
+
+class LogChecker(DiffingChecker):
+ def merge_filts(*filts):
+ filts = map(lambda f: '(' + f + ')', filts)
+ filts = '|'.join(filts)
+ return re.compile(filts, flags=re.MULTILINE)
+
+ # The reporting mechanism will print the actual filename when running in
+ # gem5, and the "golden" output will say "<removed by verify.py>". We want
+ # to strip out both versions to make comparing the output sensible.
+ in_file_filt = r'^In file: ((<removed by verify\.pl>)|([a-zA-Z0-9.:_/]*))$'
+
+ ref_filt = merge_filts(
+ r'^\nInfo: /OSCI/SystemC: Simulation stopped by user.\n',
+ r'^SystemC Simulation\n',
+ r'^\nInfo: \(I804\) /IEEE_Std_1666/deprecated: ' +
+ r'You can turn off(.*\n){7}',
+ r'^\nInfo: \(I804\) /IEEE_Std_1666/deprecated: \n' +
+ r' sc_clock\(const char(.*\n){3}',
+ warning_filt(540),
+ warning_filt(571),
+ info_filt(804),
+ in_file_filt,
+ )
+ test_filt = merge_filts(
+ r'^Global frequency set at \d* ticks per second\n',
+ r'^info: Entering event queue @ \d*\. Starting simulation\.\.\.\n',
+ r'warn: [^(]+\([^)]*\)( \[with [^]]*\])? not implemented\.\n',
+ r'warn: Ignoring request to set stack size\.\n',
+ info_filt(804),
+ in_file_filt,
+ )
+
+ def apply_filters(self, data, filts):
+ re.sub(filt, '', data)
+
+ def check(self):
+ with open(self.test) as test_f, open(self.ref) as ref_f:
+ test = re.sub(self.test_filt, '', test_f.read())
+ ref = re.sub(self.ref_filt, '', ref_f.read())
+ return self.diffing_check(ref.splitlines(True),
+ test.splitlines(True))
+
+class VcdChecker(DiffingChecker):
+ def check(self):
+ with open (self.test) as test_f, open(self.ref) as ref_f:
+ ref = ref_f.read().splitlines(True)
+ test = test_f.read().splitlines(True)
+ # Strip off the first seven lines of the test output which are
+ # date and version information.
+ test = test[7:]
+
+ return self.diffing_check(ref, test)
+
+class GoldenDir(object):
+ def __init__(self, path, platform):
+ self.path = path
+ self.platform = platform
+
+ contents = os.listdir(path)
+ suffix = '.' + platform
+ suffixed = filter(lambda c: c.endswith(suffix), contents)
+ bases = map(lambda t: t[:-len(platform)], suffixed)
+ common = filter(lambda t: not t.startswith(tuple(bases)), contents)
+
+ self.entries = {}
+ class Entry(object):
+ def __init__(self, e_path):
+ self.used = False
+ self.path = os.path.join(path, e_path)
+
+ def use(self):
+ self.used = True
+
+ for entry in contents:
+ self.entries[entry] = Entry(entry)
+
+ def entry(self, name):
+ def match(n):
+ return (n == name) or n.startswith(name + '.')
+ matches = { n: e for n, e in self.entries.items() if match(n) }
+
+ for match in matches.values():
+ match.use()
+
+ platform_name = '.'.join([ name, self.platform ])
+ if platform_name in matches:
+ return matches[platform_name].path
+ if name in matches:
+ return matches[name].path
+ else:
+ return None
+
+ def unused(self):
+ items = self.entries.items()
+ items = filter(lambda i: not i[1].used, items)
+
+ items.sort()
+ sources = []
+ i = 0
+ while i < len(items):
+ root = items[i][0]
+ sources.append(root)
+ i += 1
+ while i < len(items) and items[i][0].startswith(root):
+ i += 1
+ return sources
+