Example #1
0
 def test_number_of_input_stmts_different_with_output(self):
   args = {**self.blur.__dict__, **{'replication_factor': 1}}
   input_stmt = copy.copy(self.input_stmt)
   input_stmt.name = 'bar'
   args['input_stmts'] = [self.input_stmt, input_stmt]
   with self.assertRaises(util.SemanticError) as context:
     core.Stencil(**args)
   self.assertEqual(str(context.exception),
     'number of input tensors must be the same as output if iterate > 1 times,'
     ' currently there are 2 input(s) but 1 output(s)')
Example #2
0
 def test_haoda_type_of_input_stmts_different_with_output(self):
   args = {**self.blur.__dict__, **{'replication_factor': 1}}
   input_stmt = copy.copy(self.input_stmt)
   input_stmt.haoda_type = ir.Type('half')
   args['input_stmts'] = [input_stmt]
   with self.assertRaises(util.SemanticError) as context:
     core.Stencil(**args)
   self.assertEqual(str(context.exception),
     'input must have the same type(s) as output if iterate > 1 times, '
     'current input has type [half] but output has type [uint16]')
Example #3
0
  def setUp(self):
    self.tile_size = [233, 0]
    self.haoda_type = ir.Type('uint16')
    self.unroll_factor = 1
    self.expr_ref = ir.Ref(name='foo', idx=(233, 42), lat=None)
    self.expr = ir.Expr(operand=(self.expr_ref,), operator=())
    self.input_stmt = grammar.InputStmt(
        haoda_type=self.haoda_type, name='foo_i', tile_size=self.tile_size,
        dram=())
    self.param_stmt = grammar.ParamStmt(
        haoda_type=self.haoda_type, name='foo_p', attr=(), size=(), dram=())
    self.local_ref = ir.Ref(name='foo_l', idx=(0, 0), lat=None)
    self.local_stmt = grammar.LocalStmt(
      haoda_type=self.haoda_type, let=(), ref=self.local_ref, expr=self.expr)
    self.output_ref = ir.Ref(name='foo_o', idx=(0, 0), lat=None)
    self.output_stmt = grammar.OutputStmt(
      haoda_type=self.haoda_type, let=(), ref=self.output_ref, expr=self.expr,
      dram=())
    self.args = {
      'burst_width': 512,
      'border': 'ignore',
      'iterate': 2,
      'cluster': 'none',
      'app_name': 'foo_bar',
      'input_stmts': [self.input_stmt],
      'param_stmts': [self.param_stmt],
      'local_stmts': [self.local_stmt],
      'output_stmts': [self.output_stmt],
      'dim': len(self.tile_size),
      'tile_size': self.tile_size,
      'unroll_factor': self.unroll_factor,
      'replication_factor': self.unroll_factor}
    self.soda_mm = textx.metamodel_from_str(
      grammar.GRAMMAR, classes=grammar.CLASSES)
    self.blur = self.soda_mm.model_from_str(
r'''
kernel: blur
burst width: 512
unroll factor: 16
input uint16: input(2000, *)
local uint16: tmp(0,0)=(input(-1,0)+input(0,0)+input(1,0))/3
output uint16: output(0,0)=(tmp(0,-1)+tmp(0,0)+tmp(0,1))/3
iterate: 2
border: preserve
cluster: none
''')
    args = {**self.blur.__dict__, **{'replication_factor': 1}}
    self.stencil = core.Stencil(**args)
Example #4
0
  def test_simple_inlining(self):
    program = self.soda_mm.model_from_str(
r'''
kernel: blur
burst width: 512
unroll factor: 16
input float: t0(233, *)
local float: t1(-1, -2) = t0(0, 1)
output float: t2(4, 2) = t1(2, 3)
iterate: 1
border: preserve
cluster: none
''')
    args = {**program.__dict__, **{'replication_factor': 1}}
    stencil = core.Stencil(**args)
    inline.inline(stencil)
    self.assertEqual(len(stencil.local_stmts), 0)
    self.assertEqual(len(stencil.output_stmts), 1)
    self.assertEqual(str(stencil.output_stmts[0]),
                     'output float: t2(4, 2) = t0(3, 6)')
Example #5
0
def main():
    parser = argparse.ArgumentParser(
        prog='sodac',
        description='Stencil with Optimized Dataflow Architecture '
        '(SODA) compiler')
    parser.add_argument('--verbose',
                        '-v',
                        action='count',
                        dest='verbose',
                        help='increase verbosity')
    parser.add_argument('--quiet',
                        '-q',
                        action='count',
                        dest='quiet',
                        help='decrease verbosity')
    parser.add_argument('--recursion-limit',
                        type=int,
                        dest='recursion_limit',
                        help='override Python recursion limit')
    parser.add_argument('--burst-width',
                        type=int,
                        dest='burst_width',
                        help='override burst width')
    parser.add_argument('--unroll-factor',
                        type=int,
                        metavar='UNROLL_FACTOR',
                        dest='unroll_factor',
                        help='override unroll factor')
    parser.add_argument('--replication-factor',
                        type=int,
                        metavar='REPLICATION_FACTOR',
                        dest='replication_factor',
                        help='override replication factor')
    parser.add_argument('--tile-size',
                        type=int,
                        nargs='+',
                        metavar='TILE_SIZE',
                        dest='tile_size',
                        help='override tile size; '
                        '0 means no overriding on that dimension')
    parser.add_argument('--dram-in',
                        type=str,
                        dest='dram_in',
                        help='override DRAM configuration for input')
    parser.add_argument('--dram-out',
                        type=str,
                        dest='dram_out',
                        help='override DRAM configuration for output')
    parser.add_argument('--iterate',
                        type=int,
                        metavar='#ITERATION',
                        dest='iterate',
                        help='override iterate directive; '
                        'repeat execution multiple times iteratively')
    parser.add_argument('--border',
                        type=str,
                        metavar='(ignore|preserve)',
                        dest='border',
                        help='override border handling strategy')
    parser.add_argument('--cluster',
                        type=str,
                        metavar='(none|fine|coarse|full)',
                        dest='cluster',
                        help='module clustering level, `none` generates '
                        'standalone compute / forward modules, `fine` '
                        'fuses forwarders into compute modules, `coarse` '
                        'fuses each stage together, `full` fuses '
                        'everything together')
    parser.add_argument(type=str,
                        dest='soda_src',
                        metavar='file',
                        help='soda source code')

    xocl.add_arguments(parser.add_argument_group('Xilinx OpenCL backend'))
    iocl.add_arguments(parser.add_argument_group('Intel OpenCL backend'))
    frt.add_arguments(parser.add_argument_group('FPGA runtime backend'))
    opt_args.add_arguments(parser.add_argument_group('SODA optimizations'))

    parser.add_argument('--model-file',
                        type=str,
                        dest='model_file',
                        metavar='file',
                        help='resource model specified as json file')
    parser.add_argument('--estimation-file',
                        type=str,
                        dest='estimation_file',
                        metavar='file',
                        help='report resource and performance estimation as '
                        'json file')

    args = parser.parse_args()
    verbose = 0 if args.verbose is None else args.verbose
    quiet = 0 if args.quiet is None else args.quiet
    logging_level = (quiet -
                     verbose) * 10 + logging.getLogger().getEffectiveLevel()
    if logging_level > logging.CRITICAL:
        logging_level = logging.CRITICAL
    if logging_level < logging.DEBUG:
        logging_level = logging.DEBUG
    logging.getLogger().setLevel(logging_level)
    logger.info('set log level to %s', logging.getLevelName(logging_level))
    # TODO: check tile size

    if args.recursion_limit is not None:
        sys_recursion_limit = sys.getrecursionlimit()
        if sys_recursion_limit > args.recursion_limit:
            logger.warning(
                'Python system recursion limit (%d) > specified value (%d); '
                'the latter will be ignored', sys_recursion_limit,
                args.recursion_limit)
        else:
            sys.setrecursionlimit(args.recursion_limit)
            logger.warning('Python recursion limit is set to %d',
                           sys.getrecursionlimit())

    soda_mm = textx.metamodel_from_str(grammar.GRAMMAR,
                                       classes=grammar.CLASSES)
    logger.info('build metamodel')
    try:
        if args.soda_src == '-':
            soda_file_name = sys.stdin.name
            soda_model = soda_mm.model_from_str(sys.stdin.read())
        else:
            with open(args.soda_src, 'r') as soda_file:
                soda_model = soda_mm.model_from_str(soda_file.read())
                soda_file_name = soda_file.name
        logger.info('%s parsed as soda file', soda_file_name)
        logger.debug('soda program parsed:\n  %s',
                     str(soda_model).replace('\n', '\n  '))

        tile_size = []
        for dim in range(soda_model.dim - 1):
            if (args.tile_size is not None and dim < len(args.tile_size)
                    and args.tile_size[dim] > 0):
                tile_size.append(args.tile_size[dim])
            else:
                tile_size.append(soda_model.tile_size[dim])
        tile_size.append(0)

        if args.replication_factor is None:
            if args.unroll_factor is not None:
                unroll_factor = args.unroll_factor
            else:
                unroll_factor = soda_model.unroll_factor
            replication_factor = 1
        else:
            unroll_factor = args.replication_factor
            replication_factor = args.replication_factor

        stencil = core.Stencil(
            burst_width=args.burst_width
            if args.burst_width is not None else soda_model.burst_width,
            border=args.border
            if args.border is not None else soda_model.border,
            iterate=args.iterate
            if args.iterate is not None else soda_model.iterate,
            cluster=args.cluster
            if args.cluster is not None else soda_model.cluster,
            dram_in=args.dram_in,
            dram_out=args.dram_out,
            app_name=soda_model.app_name,
            input_stmts=soda_model.input_stmts,
            param_stmts=soda_model.param_stmts,
            local_stmts=soda_model.local_stmts,
            output_stmts=soda_model.output_stmts,
            dim=soda_model.dim,
            tile_size=tile_size,
            unroll_factor=unroll_factor,
            replication_factor=replication_factor,
            optimizations=opt_args.get_kwargs(args),
        )

        logger.debug('stencil obtained: %s', stencil)

        xocl.print_code(stencil, args, parser)
        iocl.print_code(stencil, args)
        frt.print_code(stencil, args)

        if args.estimation_file is not None:
            if args.model_file is None:
                if args.soda_src.endswith('.soda'):
                    model_file = args.soda_src[:-len('.soda')] + '_model.json'
                else:
                    logger.fatal('cannot find resource model file')
                    sys.exit(1)
            else:
                model_file = args.model_file

            def print_estimation():
                def print_estimation():
                    model.print_estimation(stencil, model_file,
                                           estimation_file)

                if args.estimation_file == '-':
                    estimation_file = sys.stdout
                    print_estimation()
                else:
                    with open(args.estimation_file, 'w') as estimation_file:
                        print_estimation()

            if model_file == '-':
                model_file = sys.stdin
                print_estimation()
            else:
                with open(model_file) as model_file:
                    print_estimation()

    except textx.exceptions.TextXSyntaxError as e:
        logger.error(e)
        sys.exit(1)
    except util.SemanticError as e:
        logger.error(e)
        sys.exit(1)
    except util.SemanticWarn as w:
        logger.warning(w)