gen.py revision 11534
111723Sar4jc@virginia.edu#! /usr/bin/python
211723Sar4jc@virginia.edu
311723Sar4jc@virginia.edu#
411723Sar4jc@virginia.edu#  Copyright (c) 2015 Advanced Micro Devices, Inc.
511723Sar4jc@virginia.edu#  All rights reserved.
611723Sar4jc@virginia.edu#
711723Sar4jc@virginia.edu#  For use for simulation and test purposes only
811723Sar4jc@virginia.edu#
911723Sar4jc@virginia.edu#  Redistribution and use in source and binary forms, with or without
1011723Sar4jc@virginia.edu#  modification, are permitted provided that the following conditions are met:
1111723Sar4jc@virginia.edu#
1211723Sar4jc@virginia.edu#  1. Redistributions of source code must retain the above copyright notice,
1311723Sar4jc@virginia.edu#  this list of conditions and the following disclaimer.
1411723Sar4jc@virginia.edu#
1511723Sar4jc@virginia.edu#  2. Redistributions in binary form must reproduce the above copyright notice,
1611723Sar4jc@virginia.edu#  this list of conditions and the following disclaimer in the documentation
1711723Sar4jc@virginia.edu#  and/or other materials provided with the distribution.
1811723Sar4jc@virginia.edu#
1911723Sar4jc@virginia.edu#  3. Neither the name of the copyright holder nor the names of its contributors
2011723Sar4jc@virginia.edu#  may be used to endorse or promote products derived from this software
2111723Sar4jc@virginia.edu#  without specific prior written permission.
2211723Sar4jc@virginia.edu#
2311723Sar4jc@virginia.edu#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2411723Sar4jc@virginia.edu#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2511723Sar4jc@virginia.edu#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2611723Sar4jc@virginia.edu#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2711723Sar4jc@virginia.edu#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2811723Sar4jc@virginia.edu#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2911723Sar4jc@virginia.edu#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3011723Sar4jc@virginia.edu#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3111723Sar4jc@virginia.edu#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3211723Sar4jc@virginia.edu#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3311723Sar4jc@virginia.edu#  POSSIBILITY OF SUCH DAMAGE.
3411723Sar4jc@virginia.edu#
3511723Sar4jc@virginia.edu#  Author: Steve Reinhardt
3611723Sar4jc@virginia.edu#
3711723Sar4jc@virginia.edu
3811723Sar4jc@virginia.eduimport sys, re
3911723Sar4jc@virginia.edu
4011723Sar4jc@virginia.edufrom m5.util import code_formatter
4111723Sar4jc@virginia.edu
4211723Sar4jc@virginia.eduif len(sys.argv) != 4:
4311723Sar4jc@virginia.edu    print "Error: need 3 args (file names)"
4412808Srobert.scheffel1@tu-dresden.de    sys.exit(0)
4511723Sar4jc@virginia.edu
4611723Sar4jc@virginia.eduheader_code = code_formatter()
4711723Sar4jc@virginia.edudecoder_code = code_formatter()
4811723Sar4jc@virginia.eduexec_code = code_formatter()
4911723Sar4jc@virginia.edu
5011723Sar4jc@virginia.edu###############
5111723Sar4jc@virginia.edu#
5211723Sar4jc@virginia.edu# Generate file prologs (includes etc.)
5311723Sar4jc@virginia.edu#
5411723Sar4jc@virginia.edu###############
5511723Sar4jc@virginia.edu
5611723Sar4jc@virginia.eduheader_code('''
5711723Sar4jc@virginia.edu#include "arch/hsail/insts/decl.hh"
5811723Sar4jc@virginia.edu#include "base/bitfield.hh"
5911723Sar4jc@virginia.edu#include "gpu-compute/hsail_code.hh"
6011723Sar4jc@virginia.edu#include "gpu-compute/wavefront.hh"
6111723Sar4jc@virginia.edu
6211723Sar4jc@virginia.edunamespace HsailISA
6311723Sar4jc@virginia.edu{
6411723Sar4jc@virginia.edu''')
6511723Sar4jc@virginia.eduheader_code.indent()
6611723Sar4jc@virginia.edu
6711723Sar4jc@virginia.edudecoder_code('''
6811723Sar4jc@virginia.edu#include "arch/hsail/gpu_decoder.hh"
6911723Sar4jc@virginia.edu#include "arch/hsail/insts/branch.hh"
7011723Sar4jc@virginia.edu#include "arch/hsail/insts/decl.hh"
7111723Sar4jc@virginia.edu#include "arch/hsail/insts/gen_decl.hh"
7211723Sar4jc@virginia.edu#include "arch/hsail/insts/mem.hh"
7311723Sar4jc@virginia.edu#include "arch/hsail/insts/mem_impl.hh"
7411723Sar4jc@virginia.edu#include "gpu-compute/brig_object.hh"
7511723Sar4jc@virginia.edu
7611723Sar4jc@virginia.edunamespace HsailISA
7711723Sar4jc@virginia.edu{
7811723Sar4jc@virginia.edu    std::vector<GPUStaticInst*> Decoder::decodedInsts;
7911723Sar4jc@virginia.edu
8011723Sar4jc@virginia.edu    GPUStaticInst*
8111723Sar4jc@virginia.edu    Decoder::decode(MachInst machInst)
8211723Sar4jc@virginia.edu    {
8311723Sar4jc@virginia.edu        using namespace Brig;
8411723Sar4jc@virginia.edu
8511723Sar4jc@virginia.edu        const BrigInstBase *ib = machInst.brigInstBase;
8611723Sar4jc@virginia.edu        const BrigObject *obj = machInst.brigObj;
8711723Sar4jc@virginia.edu
8811723Sar4jc@virginia.edu        switch(ib->opcode) {
8911723Sar4jc@virginia.edu''')
9011723Sar4jc@virginia.edudecoder_code.indent()
9111723Sar4jc@virginia.edudecoder_code.indent()
9211723Sar4jc@virginia.edu
9311723Sar4jc@virginia.eduexec_code('''
9411723Sar4jc@virginia.edu#include "arch/hsail/insts/gen_decl.hh"
9511723Sar4jc@virginia.edu#include "base/intmath.hh"
9611723Sar4jc@virginia.edu
9711723Sar4jc@virginia.edunamespace HsailISA
9811723Sar4jc@virginia.edu{
9911723Sar4jc@virginia.edu''')
10011723Sar4jc@virginia.eduexec_code.indent()
10111723Sar4jc@virginia.edu
10211723Sar4jc@virginia.edu###############
10311723Sar4jc@virginia.edu#
10411723Sar4jc@virginia.edu# Define code templates for class declarations (for header file)
10511723Sar4jc@virginia.edu#
10611723Sar4jc@virginia.edu###############
10711723Sar4jc@virginia.edu
10811723Sar4jc@virginia.edu# Basic header template for an instruction with no template parameters.
10911723Sar4jc@virginia.eduheader_template_nodt = '''
11011723Sar4jc@virginia.educlass $class_name : public $base_class
11111723Sar4jc@virginia.edu{
11211723Sar4jc@virginia.edu  public:
11311723Sar4jc@virginia.edu    typedef $base_class Base;
11411723Sar4jc@virginia.edu
11511723Sar4jc@virginia.edu    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
11611723Sar4jc@virginia.edu       : Base(ib, obj, "$opcode")
11711723Sar4jc@virginia.edu    {
11811723Sar4jc@virginia.edu    }
11911723Sar4jc@virginia.edu
12011723Sar4jc@virginia.edu    void execute(GPUDynInstPtr gpuDynInst);
12111723Sar4jc@virginia.edu};
12211723Sar4jc@virginia.edu
12311723Sar4jc@virginia.edu'''
12411723Sar4jc@virginia.edu
12511723Sar4jc@virginia.edu# Basic header template for an instruction with a single DataType
12611723Sar4jc@virginia.edu# template parameter.
12711723Sar4jc@virginia.eduheader_template_1dt = '''
12811723Sar4jc@virginia.edutemplate<typename DataType>
12911723Sar4jc@virginia.educlass $class_name : public $base_class<DataType>
13011723Sar4jc@virginia.edu{
13111723Sar4jc@virginia.edu  public:
13211723Sar4jc@virginia.edu    typedef $base_class<DataType> Base;
13311723Sar4jc@virginia.edu    typedef typename DataType::CType CType;
13411723Sar4jc@virginia.edu
13511723Sar4jc@virginia.edu    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
13611723Sar4jc@virginia.edu       : Base(ib, obj, "$opcode")
13711723Sar4jc@virginia.edu    {
13811723Sar4jc@virginia.edu    }
13911723Sar4jc@virginia.edu
14011723Sar4jc@virginia.edu    void execute(GPUDynInstPtr gpuDynInst);
14111723Sar4jc@virginia.edu};
14211723Sar4jc@virginia.edu
14311723Sar4jc@virginia.edu'''
14411723Sar4jc@virginia.edu
14511723Sar4jc@virginia.eduheader_template_1dt_noexec = '''
14611723Sar4jc@virginia.edutemplate<typename DataType>
14712749Sgiacomo.travaglini@arm.comclass $class_name : public $base_class<DataType>
14811723Sar4jc@virginia.edu{
14911723Sar4jc@virginia.edu  public:
15011723Sar4jc@virginia.edu    typedef $base_class<DataType> Base;
15111723Sar4jc@virginia.edu    typedef typename DataType::CType CType;
15211723Sar4jc@virginia.edu
15311723Sar4jc@virginia.edu    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
15411723Sar4jc@virginia.edu       : Base(ib, obj, "$opcode")
15511723Sar4jc@virginia.edu    {
15611723Sar4jc@virginia.edu    }
15711723Sar4jc@virginia.edu};
15811723Sar4jc@virginia.edu
15911723Sar4jc@virginia.edu'''
16011723Sar4jc@virginia.edu
16111723Sar4jc@virginia.edu# Same as header_template_1dt, except the base class has a second
16211723Sar4jc@virginia.edu# template parameter NumSrcOperands to allow a variable number of
16311723Sar4jc@virginia.edu# source operands.  Note that since this is implemented with an array,
16411723Sar4jc@virginia.edu# it only works for instructions where all sources are of the same
16511723Sar4jc@virginia.edu# type (like most arithmetics).
16611723Sar4jc@virginia.eduheader_template_1dt_varsrcs = '''
16711723Sar4jc@virginia.edutemplate<typename DataType>
16811723Sar4jc@virginia.educlass $class_name : public $base_class<DataType, $num_srcs>
16911723Sar4jc@virginia.edu{
17011723Sar4jc@virginia.edu  public:
17111723Sar4jc@virginia.edu    typedef $base_class<DataType, $num_srcs> Base;
17211723Sar4jc@virginia.edu    typedef typename DataType::CType CType;
17311723Sar4jc@virginia.edu
17411723Sar4jc@virginia.edu    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
17511723Sar4jc@virginia.edu       : Base(ib, obj, "$opcode")
17611723Sar4jc@virginia.edu    {
17711723Sar4jc@virginia.edu    }
17811723Sar4jc@virginia.edu
17911723Sar4jc@virginia.edu    void execute(GPUDynInstPtr gpuDynInst);
18011723Sar4jc@virginia.edu};
18111723Sar4jc@virginia.edu
18211723Sar4jc@virginia.edu'''
18311723Sar4jc@virginia.edu
18411723Sar4jc@virginia.edu# Header template for instruction with two DataType template
18511723Sar4jc@virginia.edu# parameters, one for the dest and one for the source.  This is used
18611723Sar4jc@virginia.edu# by compare and convert.
18711723Sar4jc@virginia.eduheader_template_2dt = '''
18811723Sar4jc@virginia.edutemplate<typename DestDataType, class SrcDataType>
18911723Sar4jc@virginia.educlass $class_name : public $base_class<DestDataType, SrcDataType>
19011723Sar4jc@virginia.edu{
19111723Sar4jc@virginia.edu  public:
19211723Sar4jc@virginia.edu    typedef $base_class<DestDataType, SrcDataType> Base;
19311723Sar4jc@virginia.edu    typedef typename DestDataType::CType DestCType;
19411723Sar4jc@virginia.edu    typedef typename SrcDataType::CType SrcCType;
19511723Sar4jc@virginia.edu
19611723Sar4jc@virginia.edu    $class_name(const Brig::BrigInstBase *ib, const BrigObject *obj)
19711723Sar4jc@virginia.edu       : Base(ib, obj, "$opcode")
19811723Sar4jc@virginia.edu    {
19911723Sar4jc@virginia.edu    }
20011723Sar4jc@virginia.edu
20111723Sar4jc@virginia.edu    void execute(GPUDynInstPtr gpuDynInst);
20211723Sar4jc@virginia.edu};
20311723Sar4jc@virginia.edu
20411723Sar4jc@virginia.edu'''
20511723Sar4jc@virginia.edu
20611723Sar4jc@virginia.eduheader_templates = {
20711723Sar4jc@virginia.edu    'ArithInst': header_template_1dt_varsrcs,
20811723Sar4jc@virginia.edu    'CmovInst': header_template_1dt,
20911723Sar4jc@virginia.edu    'ClassInst': header_template_1dt,
21011723Sar4jc@virginia.edu    'ShiftInst': header_template_1dt,
21111723Sar4jc@virginia.edu    'ExtractInsertInst': header_template_1dt,
21211723Sar4jc@virginia.edu    'CmpInst': header_template_2dt,
21311723Sar4jc@virginia.edu    'CvtInst': header_template_2dt,
21411723Sar4jc@virginia.edu    'LdInst': '',
21511723Sar4jc@virginia.edu    'StInst': '',
21611723Sar4jc@virginia.edu    'SpecialInstNoSrc': header_template_nodt,
21711723Sar4jc@virginia.edu    'SpecialInst1Src': header_template_nodt,
21811723Sar4jc@virginia.edu    'SpecialInstNoSrcNoDest': '',
21911723Sar4jc@virginia.edu}
22011723Sar4jc@virginia.edu
22111723Sar4jc@virginia.edu###############
22211723Sar4jc@virginia.edu#
22311723Sar4jc@virginia.edu# Define code templates for exec functions
22411723Sar4jc@virginia.edu#
22511723Sar4jc@virginia.edu###############
22611723Sar4jc@virginia.edu
22711723Sar4jc@virginia.edu# exec function body
22811723Sar4jc@virginia.eduexec_template_nodt_nosrc = '''
22911723Sar4jc@virginia.eduvoid
23011723Sar4jc@virginia.edu$class_name::execute(GPUDynInstPtr gpuDynInst)
23111723Sar4jc@virginia.edu{
23211723Sar4jc@virginia.edu    Wavefront *w = gpuDynInst->wavefront();
23311723Sar4jc@virginia.edu
23411723Sar4jc@virginia.edu    typedef Base::DestCType DestCType;
23511723Sar4jc@virginia.edu
23611723Sar4jc@virginia.edu    const VectorMask &mask = w->get_pred();
23711723Sar4jc@virginia.edu
23811723Sar4jc@virginia.edu    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
23911723Sar4jc@virginia.edu        if (mask[lane]) {
24011723Sar4jc@virginia.edu            DestCType dest_val = $expr;
24111723Sar4jc@virginia.edu            this->dest.set(w, lane, dest_val);
24211723Sar4jc@virginia.edu        }
24311723Sar4jc@virginia.edu    }
24411723Sar4jc@virginia.edu}
24511723Sar4jc@virginia.edu
24611723Sar4jc@virginia.edu'''
24711723Sar4jc@virginia.edu
24811723Sar4jc@virginia.eduexec_template_nodt_1src = '''
24911723Sar4jc@virginia.eduvoid
25011723Sar4jc@virginia.edu$class_name::execute(GPUDynInstPtr gpuDynInst)
25111723Sar4jc@virginia.edu{
25211723Sar4jc@virginia.edu    Wavefront *w = gpuDynInst->wavefront();
25311723Sar4jc@virginia.edu
25411723Sar4jc@virginia.edu    typedef Base::DestCType DestCType;
25511723Sar4jc@virginia.edu    typedef Base::SrcCType  SrcCType;
25611723Sar4jc@virginia.edu
25711723Sar4jc@virginia.edu    const VectorMask &mask = w->get_pred();
25811723Sar4jc@virginia.edu
25911723Sar4jc@virginia.edu    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
26011723Sar4jc@virginia.edu        if (mask[lane]) {
26111723Sar4jc@virginia.edu            SrcCType src_val0 = this->src0.get<SrcCType>(w, lane);
26211723Sar4jc@virginia.edu            DestCType dest_val = $expr;
26311723Sar4jc@virginia.edu
26411723Sar4jc@virginia.edu            this->dest.set(w, lane, dest_val);
26511723Sar4jc@virginia.edu        }
26611723Sar4jc@virginia.edu    }
26711723Sar4jc@virginia.edu}
26811723Sar4jc@virginia.edu
26911723Sar4jc@virginia.edu'''
27011723Sar4jc@virginia.edu
27111723Sar4jc@virginia.eduexec_template_1dt_varsrcs = '''
27211723Sar4jc@virginia.edutemplate<typename DataType>
27311723Sar4jc@virginia.eduvoid
27411723Sar4jc@virginia.edu$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
27511723Sar4jc@virginia.edu{
27611723Sar4jc@virginia.edu    Wavefront *w = gpuDynInst->wavefront();
27711723Sar4jc@virginia.edu
27811723Sar4jc@virginia.edu    const VectorMask &mask = w->get_pred();
27911723Sar4jc@virginia.edu
28011723Sar4jc@virginia.edu    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
28111723Sar4jc@virginia.edu        if (mask[lane]) {
28211723Sar4jc@virginia.edu            CType dest_val;
28311723Sar4jc@virginia.edu            if ($dest_is_src_flag) {
28411723Sar4jc@virginia.edu                dest_val = this->dest.template get<CType>(w, lane);
28511723Sar4jc@virginia.edu            }
28611723Sar4jc@virginia.edu
28712749Sgiacomo.travaglini@arm.com            CType src_val[$num_srcs];
28811723Sar4jc@virginia.edu
28912808Srobert.scheffel1@tu-dresden.de            for (int i = 0; i < $num_srcs; ++i) {
29012808Srobert.scheffel1@tu-dresden.de                src_val[i] = this->src[i].template get<CType>(w, lane);
29112808Srobert.scheffel1@tu-dresden.de            }
29212808Srobert.scheffel1@tu-dresden.de
29312808Srobert.scheffel1@tu-dresden.de            dest_val = (CType)($expr);
29412808Srobert.scheffel1@tu-dresden.de
29512808Srobert.scheffel1@tu-dresden.de            this->dest.set(w, lane, dest_val);
29611723Sar4jc@virginia.edu        }
29712808Srobert.scheffel1@tu-dresden.de    }
29812808Srobert.scheffel1@tu-dresden.de}
29912808Srobert.scheffel1@tu-dresden.de
30012808Srobert.scheffel1@tu-dresden.de'''
30112808Srobert.scheffel1@tu-dresden.de
30212808Srobert.scheffel1@tu-dresden.deexec_template_1dt_3srcs = '''
30312808Srobert.scheffel1@tu-dresden.detemplate<typename DataType>
30412808Srobert.scheffel1@tu-dresden.devoid
30512808Srobert.scheffel1@tu-dresden.de$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
30612808Srobert.scheffel1@tu-dresden.de{
30712808Srobert.scheffel1@tu-dresden.de    Wavefront *w = gpuDynInst->wavefront();
30812808Srobert.scheffel1@tu-dresden.de
30912808Srobert.scheffel1@tu-dresden.de    typedef typename Base::Src0CType Src0T;
31012808Srobert.scheffel1@tu-dresden.de    typedef typename Base::Src1CType Src1T;
31112808Srobert.scheffel1@tu-dresden.de    typedef typename Base::Src2CType Src2T;
31211723Sar4jc@virginia.edu
31312808Srobert.scheffel1@tu-dresden.de    const VectorMask &mask = w->get_pred();
31412808Srobert.scheffel1@tu-dresden.de
31512808Srobert.scheffel1@tu-dresden.de    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
31611723Sar4jc@virginia.edu        if (mask[lane]) {
31712808Srobert.scheffel1@tu-dresden.de            CType dest_val;
31812808Srobert.scheffel1@tu-dresden.de
31911723Sar4jc@virginia.edu            if ($dest_is_src_flag) {
32011723Sar4jc@virginia.edu                dest_val = this->dest.template get<CType>(w, lane);
32111723Sar4jc@virginia.edu            }
32212749Sgiacomo.travaglini@arm.com
32311723Sar4jc@virginia.edu            Src0T src_val0 = this->src0.template get<Src0T>(w, lane);
32412808Srobert.scheffel1@tu-dresden.de            Src1T src_val1 = this->src1.template get<Src1T>(w, lane);
32512808Srobert.scheffel1@tu-dresden.de            Src2T src_val2 = this->src2.template get<Src2T>(w, lane);
32612808Srobert.scheffel1@tu-dresden.de
32712808Srobert.scheffel1@tu-dresden.de            dest_val = $expr;
32812808Srobert.scheffel1@tu-dresden.de
32912808Srobert.scheffel1@tu-dresden.de            this->dest.set(w, lane, dest_val);
33012808Srobert.scheffel1@tu-dresden.de        }
33111723Sar4jc@virginia.edu    }
33212808Srobert.scheffel1@tu-dresden.de}
33312808Srobert.scheffel1@tu-dresden.de
33412808Srobert.scheffel1@tu-dresden.de'''
33512808Srobert.scheffel1@tu-dresden.de
33612808Srobert.scheffel1@tu-dresden.deexec_template_1dt_2src_1dest = '''
33712808Srobert.scheffel1@tu-dresden.detemplate<typename DataType>
33812808Srobert.scheffel1@tu-dresden.devoid
33912808Srobert.scheffel1@tu-dresden.de$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
34012808Srobert.scheffel1@tu-dresden.de{
34112808Srobert.scheffel1@tu-dresden.de    Wavefront *w = gpuDynInst->wavefront();
34212808Srobert.scheffel1@tu-dresden.de
34312808Srobert.scheffel1@tu-dresden.de    typedef typename Base::DestCType DestT;
34412808Srobert.scheffel1@tu-dresden.de    typedef CType Src0T;
34512808Srobert.scheffel1@tu-dresden.de    typedef typename Base::Src1CType Src1T;
34612808Srobert.scheffel1@tu-dresden.de
34712808Srobert.scheffel1@tu-dresden.de    const VectorMask &mask = w->get_pred();
34812808Srobert.scheffel1@tu-dresden.de
34912808Srobert.scheffel1@tu-dresden.de    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
35012808Srobert.scheffel1@tu-dresden.de        if (mask[lane]) {
35112808Srobert.scheffel1@tu-dresden.de            DestT dest_val;
35212808Srobert.scheffel1@tu-dresden.de            if ($dest_is_src_flag) {
35312808Srobert.scheffel1@tu-dresden.de                dest_val = this->dest.template get<DestT>(w, lane);
35412808Srobert.scheffel1@tu-dresden.de            }
35512808Srobert.scheffel1@tu-dresden.de            Src0T src_val0 = this->src0.template get<Src0T>(w, lane);
35611962Sar4jc@virginia.edu            Src1T src_val1 = this->src1.template get<Src1T>(w, lane);
35712808Srobert.scheffel1@tu-dresden.de
35811723Sar4jc@virginia.edu            dest_val = $expr;
35912808Srobert.scheffel1@tu-dresden.de
36012808Srobert.scheffel1@tu-dresden.de            this->dest.set(w, lane, dest_val);
36112808Srobert.scheffel1@tu-dresden.de        }
36211723Sar4jc@virginia.edu    }
36312808Srobert.scheffel1@tu-dresden.de}
36412808Srobert.scheffel1@tu-dresden.de
36511723Sar4jc@virginia.edu'''
36611723Sar4jc@virginia.edu
36711723Sar4jc@virginia.eduexec_template_shift = '''
36812749Sgiacomo.travaglini@arm.comtemplate<typename DataType>
36911723Sar4jc@virginia.eduvoid
37011723Sar4jc@virginia.edu$class_name<DataType>::execute(GPUDynInstPtr gpuDynInst)
37111723Sar4jc@virginia.edu{
37211723Sar4jc@virginia.edu    Wavefront *w = gpuDynInst->wavefront();
37311723Sar4jc@virginia.edu
37411723Sar4jc@virginia.edu    const VectorMask &mask = w->get_pred();
37511723Sar4jc@virginia.edu    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
37611723Sar4jc@virginia.edu        if (mask[lane]) {
37712749Sgiacomo.travaglini@arm.com            CType dest_val;
37811723Sar4jc@virginia.edu
37911723Sar4jc@virginia.edu            if ($dest_is_src_flag) {
38011723Sar4jc@virginia.edu                dest_val = this->dest.template get<CType>(w, lane);
38111723Sar4jc@virginia.edu            }
38211723Sar4jc@virginia.edu
38311723Sar4jc@virginia.edu            CType src_val0 = this->src0.template get<CType>(w, lane);
38411723Sar4jc@virginia.edu            uint32_t src_val1 = this->src1.template get<uint32_t>(w, lane);
38512749Sgiacomo.travaglini@arm.com
38612749Sgiacomo.travaglini@arm.com            dest_val = $expr;
38711723Sar4jc@virginia.edu
38811723Sar4jc@virginia.edu            this->dest.set(w, lane, dest_val);
38911723Sar4jc@virginia.edu        }
39011723Sar4jc@virginia.edu    }
39111723Sar4jc@virginia.edu}
39211723Sar4jc@virginia.edu
39311723Sar4jc@virginia.edu'''
39411723Sar4jc@virginia.edu
39511723Sar4jc@virginia.eduexec_template_2dt = '''
39611723Sar4jc@virginia.edutemplate<typename DestDataType, class SrcDataType>
39711723Sar4jc@virginia.eduvoid
39811723Sar4jc@virginia.edu$class_name<DestDataType, SrcDataType>::execute(GPUDynInstPtr gpuDynInst)
39911723Sar4jc@virginia.edu{
40011723Sar4jc@virginia.edu    Wavefront *w = gpuDynInst->wavefront();
40111723Sar4jc@virginia.edu
40211723Sar4jc@virginia.edu    const VectorMask &mask = w->get_pred();
40311723Sar4jc@virginia.edu
40411723Sar4jc@virginia.edu    for (int lane = 0; lane < w->computeUnit->wfSize(); ++lane) {
40511723Sar4jc@virginia.edu        if (mask[lane]) {
40611723Sar4jc@virginia.edu            DestCType dest_val;
40711723Sar4jc@virginia.edu            SrcCType src_val[$num_srcs];
408
409            for (int i = 0; i < $num_srcs; ++i) {
410                src_val[i] = this->src[i].template get<SrcCType>(w, lane);
411            }
412
413            dest_val = $expr;
414
415            this->dest.set(w, lane, dest_val);
416        }
417    }
418}
419
420'''
421
422exec_templates = {
423    'ArithInst': exec_template_1dt_varsrcs,
424    'CmovInst': exec_template_1dt_3srcs,
425    'ExtractInsertInst': exec_template_1dt_3srcs,
426    'ClassInst': exec_template_1dt_2src_1dest,
427    'CmpInst': exec_template_2dt,
428    'CvtInst': exec_template_2dt,
429    'LdInst': '',
430    'StInst': '',
431    'SpecialInstNoSrc': exec_template_nodt_nosrc,
432    'SpecialInst1Src': exec_template_nodt_1src,
433    'SpecialInstNoSrcNoDest': '',
434}
435
436###############
437#
438# Define code templates for the decoder cases
439#
440###############
441
442# decode template for nodt-opcode case
443decode_nodt_template = '''
444  case BRIG_OPCODE_$brig_opcode_upper: return $constructor(ib, obj);'''
445
446decode_case_prolog_class_inst = '''
447  case BRIG_OPCODE_$brig_opcode_upper:
448    {
449        //const BrigOperandBase *baseOp = obj->getOperand(ib->operands[1]);
450        BrigType16_t type = ((BrigInstSourceType*)ib)->sourceType;
451        //switch (baseOp->kind) {
452        //    case BRIG_OPERAND_REG:
453        //        type = ((const BrigOperandReg*)baseOp)->type;
454        //        break;
455        //    case BRIG_OPERAND_IMMED:
456        //        type = ((const BrigOperandImmed*)baseOp)->type;
457        //        break;
458        //    default:
459        //        fatal("CLASS unrecognized kind of operand %d\\n",
460        //               baseOp->kind);
461        //}
462        switch (type) {'''
463
464# common prolog for 1dt- or 2dt-opcode case: switch on data type
465decode_case_prolog = '''
466  case BRIG_OPCODE_$brig_opcode_upper:
467    {
468        switch (ib->type) {'''
469
470# single-level decode case entry (for 1dt opcodes)
471decode_case_entry = \
472'      case BRIG_TYPE_$type_name: return $constructor(ib, obj);'
473
474decode_store_prolog = \
475'      case BRIG_TYPE_$type_name: {'
476
477decode_store_case_epilog = '''
478    }'''
479
480decode_store_case_entry = \
481'          return $constructor(ib, obj);'
482
483# common epilog for type switch
484decode_case_epilog = '''
485          default: fatal("$brig_opcode_upper: unrecognized type %d\\n",
486              ib->type);
487        }
488    }
489    break;'''
490
491# Additional templates for nested decode on a second type field (for
492# compare and convert).  These are used in place of the
493# decode_case_entry template to create a second-level switch on on the
494# second type field inside each case of the first-level type switch.
495# Because the name and location of the second type can vary, the Brig
496# instruction type must be provided in $brig_type, and the name of the
497# second type field must be provided in $type_field.
498decode_case2_prolog = '''
499        case BRIG_TYPE_$type_name:
500          switch (((Brig$brig_type*)ib)->$type2_field) {'''
501
502decode_case2_entry = \
503'          case BRIG_TYPE_$type2_name: return $constructor(ib, obj);'
504
505decode_case2_epilog = '''
506          default: fatal("$brig_opcode_upper: unrecognized $type2_field %d\\n",
507                         ((Brig$brig_type*)ib)->$type2_field);
508        }
509        break;'''
510
511# Figure out how many source operands an expr needs by looking for the
512# highest-numbered srcN value referenced.  Since sources are numbered
513# starting at 0, the return value is N+1.
514def num_src_operands(expr):
515    if expr.find('src2') != -1:
516        return 3
517    elif expr.find('src1') != -1:
518        return 2
519    elif expr.find('src0') != -1:
520        return 1
521    else:
522        return 0
523
524###############
525#
526# Define final code generation methods
527#
528# The gen_nodt, and gen_1dt, and gen_2dt methods are the interface for
529# generating actual instructions.
530#
531###############
532
533# Generate class declaration, exec function, and decode switch case
534# for an brig_opcode with a single-level type switch.  The 'types'
535# parameter is a list or tuple of types for which the instruction
536# should be instantiated.
537def gen(brig_opcode, types=None, expr=None, base_class='ArithInst',
538        type2_info=None, constructor_prefix='new ', is_store=False):
539    brig_opcode_upper = brig_opcode.upper()
540    class_name = brig_opcode
541    opcode = class_name.lower()
542
543    if base_class == 'ArithInst':
544        # note that expr must be provided with ArithInst so we can
545        # derive num_srcs for the template
546        assert expr
547
548    if expr:
549        # Derive several bits of info from expr.  If expr is not used,
550        # this info will be irrelevant.
551        num_srcs = num_src_operands(expr)
552        # if the RHS expression includes 'dest', then we're doing an RMW
553        # on the reg and we need to treat it like a source
554        dest_is_src = expr.find('dest') != -1
555        dest_is_src_flag = str(dest_is_src).lower() # for C++
556        if base_class in ['ShiftInst']:
557            expr = re.sub(r'\bsrc(\d)\b', r'src_val\1', expr)
558        elif base_class in ['ArithInst', 'CmpInst', 'CvtInst']:
559            expr = re.sub(r'\bsrc(\d)\b', r'src_val[\1]', expr)
560        else:
561            expr = re.sub(r'\bsrc(\d)\b', r'src_val\1', expr)
562        expr = re.sub(r'\bdest\b', r'dest_val', expr)
563
564    # Strip template arguments off of base class before looking up
565    # appropriate templates
566    base_class_base = re.sub(r'<.*>$', '', base_class)
567    header_code(header_templates[base_class_base])
568
569    if base_class.startswith('SpecialInst'):
570        exec_code(exec_templates[base_class_base])
571    elif base_class.startswith('ShiftInst'):
572        header_code(exec_template_shift)
573    else:
574        header_code(exec_templates[base_class_base])
575
576    if not types or isinstance(types, str):
577        # Just a single type
578        constructor = constructor_prefix + class_name
579        decoder_code(decode_nodt_template)
580    else:
581        # multiple types, need at least one level of decode
582        if brig_opcode == 'Class':
583            decoder_code(decode_case_prolog_class_inst)
584        else:
585            decoder_code(decode_case_prolog)
586        if not type2_info:
587            if not is_store:
588                # single list of types, to basic one-level decode
589                for type_name in types:
590                    full_class_name = '%s<%s>' % (class_name, type_name.upper())
591                    constructor = constructor_prefix + full_class_name
592                    decoder_code(decode_case_entry)
593            else:
594                # single list of types, to basic one-level decode
595                for type_name in types:
596                    decoder_code(decode_store_prolog)
597                    type_size = int(re.findall(r'[0-9]+', type_name)[0])
598                    src_size = 32
599                    type_type = type_name[0]
600                    full_class_name = '%s<%s,%s>' % (class_name, \
601                                                     type_name.upper(), \
602                                                     '%s%d' % \
603                                                     (type_type.upper(), \
604                                                     type_size))
605                    constructor = constructor_prefix + full_class_name
606                    decoder_code(decode_store_case_entry)
607                    decoder_code(decode_store_case_epilog)
608        else:
609            # need secondary type switch (convert, compare)
610            # unpack extra info on second switch
611            (type2_field, types2) = type2_info
612            brig_type = 'Inst%s' % brig_opcode
613            for type_name in types:
614                decoder_code(decode_case2_prolog)
615                fmt = '%s<%s,%%s>' % (class_name, type_name.upper())
616                for type2_name in types2:
617                    full_class_name = fmt % type2_name.upper()
618                    constructor = constructor_prefix + full_class_name
619                    decoder_code(decode_case2_entry)
620
621                decoder_code(decode_case2_epilog)
622
623        decoder_code(decode_case_epilog)
624
625###############
626#
627# Generate instructions
628#
629###############
630
631# handy abbreviations for common sets of types
632
633# arithmetic ops are typically defined only on 32- and 64-bit sizes
634arith_int_types = ('S32', 'U32', 'S64', 'U64')
635arith_float_types = ('F32', 'F64')
636arith_types = arith_int_types + arith_float_types
637
638bit_types = ('B1', 'B32', 'B64')
639
640all_int_types = ('S8', 'U8', 'S16', 'U16') + arith_int_types
641
642# I think you might be able to do 'f16' memory ops too, but we'll
643# ignore them for now.
644mem_types = all_int_types + arith_float_types
645mem_atom_types = all_int_types + ('B32', 'B64')
646
647##### Arithmetic & logical operations
648gen('Add', arith_types, 'src0 + src1')
649gen('Sub', arith_types, 'src0 - src1')
650gen('Mul', arith_types, 'src0 * src1')
651gen('Div', arith_types, 'src0 / src1')
652gen('Min', arith_types, 'std::min(src0, src1)')
653gen('Max', arith_types, 'std::max(src0, src1)')
654gen('Gcnmin', arith_types, 'std::min(src0, src1)')
655
656gen('CopySign', arith_float_types,
657    'src1 < 0 ? -std::abs(src0) : std::abs(src0)')
658gen('Sqrt', arith_float_types, 'sqrt(src0)')
659gen('Floor', arith_float_types, 'floor(src0)')
660
661# "fast" sqrt... same as slow for us
662gen('Nsqrt', arith_float_types, 'sqrt(src0)')
663gen('Nrsqrt', arith_float_types, '1.0/sqrt(src0)')
664gen('Nrcp', arith_float_types, '1.0/src0')
665gen('Fract', arith_float_types,
666    '(src0 >= 0.0)?(src0-floor(src0)):(floor(src0)-src0)')
667
668gen('Ncos', arith_float_types, 'cos(src0)');
669gen('Nsin', arith_float_types, 'sin(src0)');
670
671gen('And', bit_types, 'src0 & src1')
672gen('Or', bit_types,  'src0 | src1')
673gen('Xor', bit_types, 'src0 ^ src1')
674
675gen('Bitselect', bit_types, '(src1 & src0) | (src2 & ~src0)')
676gen('Firstbit',bit_types, 'firstbit(src0)')
677gen('Popcount', ('B32', 'B64'), '__builtin_popcount(src0)')
678
679gen('Shl', arith_int_types, 'src0 << (unsigned)src1', 'ShiftInst')
680gen('Shr', arith_int_types, 'src0 >> (unsigned)src1', 'ShiftInst')
681
682# gen('Mul_hi', types=('s32','u32', '??'))
683# gen('Mul24', types=('s32','u32', '??'))
684gen('Rem', arith_int_types, 'src0 - ((src0 / src1) * src1)')
685
686gen('Abs', arith_types, 'std::abs(src0)')
687gen('Neg', arith_types, '-src0')
688
689gen('Mov', bit_types, 'src0')
690gen('Not', bit_types, 'heynot(src0)')
691
692# mad and fma differ only in rounding behavior, which we don't emulate
693# also there's an integer form of mad, but not of fma
694gen('Mad', arith_types, 'src0 * src1 + src2')
695gen('Fma', arith_float_types, 'src0 * src1 + src2')
696
697#native floating point operations
698gen('Nfma', arith_float_types, 'src0 * src1 + src2')
699
700gen('Cmov', bit_types, 'src0 ? src1 : src2', 'CmovInst')
701gen('BitAlign', bit_types, '(src0 << src2)|(src1 >> (32 - src2))')
702gen('ByteAlign', bit_types, '(src0 << 8 * src2)|(src1 >> (32 - 8 * src2))')
703
704# see base/bitfield.hh
705gen('BitExtract', arith_int_types, 'bits(src0, src1, src1 + src2 - 1)',
706    'ExtractInsertInst')
707
708gen('BitInsert', arith_int_types, 'insertBits(dest, src1, src2, src0)',
709    'ExtractInsertInst')
710
711##### Compare
712gen('Cmp', ('B1', 'S32', 'U32', 'F32'), 'compare(src0, src1, this->cmpOp)',
713    'CmpInst', ('sourceType', arith_types + bit_types))
714gen('Class', arith_float_types, 'fpclassify(src0,src1)','ClassInst')
715
716##### Conversion
717
718# Conversion operations are only defined on B1, not B32 or B64
719cvt_types = ('B1',) + mem_types
720
721gen('Cvt', cvt_types, 'src0', 'CvtInst', ('sourceType', cvt_types))
722
723
724##### Load & Store
725gen('Lda', mem_types, base_class = 'LdInst', constructor_prefix='decode')
726gen('Ld', mem_types, base_class = 'LdInst', constructor_prefix='decode')
727gen('St', mem_types, base_class = 'StInst', constructor_prefix='decode',
728    is_store=True)
729gen('Atomic', mem_atom_types, base_class='StInst', constructor_prefix='decode')
730gen('AtomicNoRet', mem_atom_types, base_class='StInst',
731    constructor_prefix='decode')
732
733gen('Cbr', base_class = 'LdInst', constructor_prefix='decode')
734gen('Br', base_class = 'LdInst', constructor_prefix='decode')
735
736##### Special operations
737def gen_special(brig_opcode, expr, dest_type='U32'):
738    num_srcs = num_src_operands(expr)
739    if num_srcs == 0:
740        base_class = 'SpecialInstNoSrc<%s>' % dest_type
741    elif num_srcs == 1:
742        base_class = 'SpecialInst1Src<%s>' % dest_type
743    else:
744        assert false
745
746    gen(brig_opcode, None, expr, base_class)
747
748gen_special('WorkItemId', 'w->workitemid[src0][lane]')
749gen_special('WorkItemAbsId',
750    'w->workitemid[src0][lane] + (w->workgroupid[src0] * w->workgroupsz[src0])')
751gen_special('WorkGroupId', 'w->workgroupid[src0]')
752gen_special('WorkGroupSize', 'w->workgroupsz[src0]')
753gen_special('CurrentWorkGroupSize', 'w->workgroupsz[src0]')
754gen_special('GridSize', 'w->gridsz[src0]')
755gen_special('GridGroups',
756    'divCeil(w->gridsz[src0],w->workgroupsz[src0])')
757gen_special('LaneId', 'lane')
758gen_special('WaveId', 'w->dynwaveid')
759gen_special('Clock', 'w->computeUnit->shader->tick_cnt', 'U64')
760
761# gen_special('CU'', ')
762
763gen('Ret', base_class='SpecialInstNoSrcNoDest')
764gen('Barrier', base_class='SpecialInstNoSrcNoDest')
765gen('MemFence', base_class='SpecialInstNoSrcNoDest')
766
767# Map magic instructions to the BrigSyscall opcode
768# Magic instructions are defined in magic.hh
769#
770# In the future, real HSA kernel system calls can be implemented and coexist
771# with magic instructions.
772gen('Call', base_class='SpecialInstNoSrcNoDest')
773
774###############
775#
776# Generate file epilogs
777#
778###############
779header_code.dedent()
780header_code('''
781} // namespace HsailISA
782''')
783
784# close off main decode switch
785decoder_code.dedent()
786decoder_code.dedent()
787decoder_code('''
788          default: fatal("unrecognized Brig opcode %d\\n", ib->opcode);
789        } // end switch(ib->opcode)
790    } // end decode()
791} // namespace HsailISA
792''')
793
794exec_code.dedent()
795exec_code('''
796} // namespace HsailISA
797''')
798
799###############
800#
801# Output accumulated code to files
802#
803###############
804header_code.write(sys.argv[1])
805decoder_code.write(sys.argv[2])
806exec_code.write(sys.argv[3])
807