#!/usr/bin/env python
#
# Copyright 2008 Free Software Foundation, Inc.
# 
# This file is part of GNU Radio
# 
# GNU Radio is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# 
# GNU Radio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

"""
Run synthetic.py for npipes in [1,16], nstages in [1,16]
"""

import re
import sys
import os
import tempfile
from optparse import OptionParser


def write_shell_script(f, data_filename, description, ncores, gflops, max_pipes_and_stages):
    """
    f is the file to write the script to
    data_filename is the where the data ends up
    description describes the machine
    ncores is the number of cores (used to size the workload)
    gflops is the estimated GFLOPS per core (used to size the workload)
    """

    f.write("#!/bin/sh\n")
    f.write("(\n")
    if description:
        f.write("echo '#D %s'\n" % (description,))

    for npipes in range(1, max_pipes_and_stages + 1):
        for nstages in range(1, max_pipes_and_stages + 1):
            # We'd like each run of synthetic to take ~10 seconds
            desired_time_per_run = 10
            est_gflops_avail = min(nstages * npipes, ncores) * gflops
            nsamples = (est_gflops_avail * desired_time_per_run)/(512.0 * nstages * npipes)
            nsamples = int(nsamples * 1e9)

            cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % (nstages, npipes, nsamples)
            f.write(cmd)
            f.write('if test $? -ge 128; then exit 128; fi\n')

    f.write(") 2>&1 | grep --line-buffered -v '^>>>' | tee %s\n" % (data_filename,))
    f.flush()
    
    

def main():
    description = """%prog gathers multiprocessor scaling data using the ./synthetic.py benchmark.
All combinations of npipes and nstages between 1 and --max-pipes-and-stages are tried.
The -n and -f options provides hints used to size the workload.  We'd like each run
of synthetic to take about 10 seconds.  For the full 16x16 case this results in a
total runtime of about 43 minutes, assuming that your values for -n and -f are reasonable.
For x86 machines, assume 3 FLOPS per processor Hz. E.g., 3 GHz machine -> 9 GFLOPS.
plot_flops.py will make pretty graphs from the output data generated by %prog.
"""
    usage = "usage: %prog [options] output.dat"
    parser = OptionParser(usage=usage, description=description)
    parser.add_option("-d", "--description", metavar="DESC",
                      help="machine description, e.g., \"Dual quad-core Xeon 3 GHz\"", default=None)
    parser.add_option("-n", "--ncores", type="int", default=1,
                      help="number of processor cores [default=%default]")
    parser.add_option("-g", "--gflops", metavar="GFLOPS", type="float", default=3.0,
                      help="estimated GFLOPS per core [default=%default]")
    parser.add_option("-m", "--max-pipes-and-stages", metavar="MAX", type="int", default=16,
                      help="maximum number of pipes and stages to use [default=%default]")
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.print_help()
        raise SystemExit, 1

    output_filename = args[0]

    shell = os.popen("/bin/sh", "w")
    
    write_shell_script(shell,
                       output_filename,
                       options.description,
                       options.ncores,
                       options.gflops,
                       options.max_pipes_and_stages)
    
if __name__ == '__main__':
    main()

