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