OpenCores
URL https://opencores.org/ocsvn/theia_gpu/theia_gpu/trunk

Subversion Repositories theia_gpu

[/] [theia_gpu/] [branches/] [beta_2.0/] [compiler/] [src/] [cp_compiler/] [parser.y] - Rev 229

Compare with Previous | Blame | View Log


/**********************************************************************************
Theia, Ray Cast Programable graphic Processing Unit.
Copyright (C) 2012  Diego Valverde (diego.valverde.g@gmail.com)

This program 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 2
of the License, or (at your option) any later version.

This program 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.

***********************************************************************************/

 
%require "2.4.1"
%skeleton "lalr1.cc"
%defines
%error-verbose
%locations
%define namespace "Theia"
%define parser_class_name "Parser"
%parse-param { Theia::Scanner &scanner }
%parse-param { std::map<std::string,unsigned int>  & mSymbolMap }
%parse-param { std::vector< CControlInstruction > &mInstructions }
%parse-param { bool &mGenerateFixedPointArithmetic }
%lex-param   { Theia::Scanner &scanner }

%code requires {
        #include <string>
        #include <sstream>
        #include <iomanip>
        #include <bitset>
        #include <map>
        #include "Instruction.h"
        #include <vector>
        

        // We want to return a string
        #define YYSTYPE std::string

        
                namespace Theia
                {
                        // Forward-declare the Scanner class; the Parser needs to be assigned a 
                        // Scanner, but the Scanner can't be declared without the Parser
                        class Scanner;
                
                        // We use a map to store the INI data
                        typedef std::map<std::string, std::map<std::string, std::string> > mapData;
                        
                        
                        


                }
        
}

%code 
{
        #include "Instruction.h"
        #include <vector>
        CControlInstruction I;
        std::vector< unsigned int > gBranchStack;
        static int gInsertedInstructions = 0;
        static int gWhileLoopAddress = 0;
#define FUNCTION_PARAM_START_REGION 4
#define FUNCTION_PARAM_LAST_REGION  7
        std::map<std::string, unsigned int> gVaribleMap;
        
#define AUTOVAR_START_REGION 9
#define TEMP_VAR_START_OFFSET 128
unsigned int gAutoVarIndex = AUTOVAR_START_REGION;

unsigned int gFunctionParameterIndex = FUNCTION_PARAM_START_REGION;
//----------------------------------------------------------
int GetCurrentLineNumber( const Theia::Parser::location_type &loc )
{
                int ret = -1;
                std::stringstream ss2;
                std::string where;
                ss2 << loc;
                ss2 >> where;
                where.erase(where.find_first_of("."));
                std::stringstream ss3;
                ss3 << where;
                ss3 >> ret;
                return ret;
}
//----------------------------------------------------------
unsigned int GetAddressFromIdentifier( std::string aIdentifier, Theia::Parser::location_type  yylloc )
{
        if (aIdentifier.find("R") != std::string::npos)
        {
                return atoi(aIdentifier.c_str()+1);
        }
        if (gVaribleMap.find(aIdentifier) == gVaribleMap.end())
        {
                        std::ostringstream ret;
                        ret << "Undefined variable '" << aIdentifier << "' at line " << yylloc << " \n";
                        throw ret.str();
        }
                
        return gVaribleMap[ aIdentifier ];

}
//----------------------------------------------------------
unsigned int gTempRegisterIndex = TEMP_VAR_START_OFFSET;
//----------------------------------------------------------                    
unsigned int GetFreeTempRegister( void )
{
        
        return gTempRegisterIndex++;
        
}
//----------------------------------------------------------                    
void ResetTempRegisterIndex( void )
{
        
        gTempRegisterIndex = TEMP_VAR_START_OFFSET;
}
//----------------------------------------------------------
unsigned int AllocateVariable( )
{
                gAutoVarIndex++;
                return gAutoVarIndex;
        
}       
//----------------------------------------------------------
        // Prototype for the yylex function
        static int yylex(Theia::Parser::semantic_type * yylval,
                         Theia::Parser::location_type * yylloc,
                         Theia::Scanner &scanner);
}

%token SHL SHR SCALAR RETURN EXIT EQUAL NOT_EQUAL GREATER_THAN LESS_THAN LESS_OR_EQUAL_THAN GREATER_OR_EQUAL_THAN IF ELSE OPEN_ROUND_BRACE CLOSE_ROUND_BRACE OPEN_BRACE CLOSE_BRACE ASSIGN ADD DECCONST HEXCONST BINCONST EOS MINUS 
%token IDENTIFIER  COMMA OPEN_SQUARE_BRACE CLOSE_SQUARE_BRACE WHILE START BITWISE_AND BITWISE_OR COPY_DATA_BLOCK COPY_CODE_BLOCK BLOCK_TRANSFER_IN_PROGRESS
%%

statement_list: //empty
        |
        statement_list statement
        |
        statement
        ;

statement
        :
        START LESS_THAN constant GREATER_THAN EOS
        {
        
                unsigned int ImmediateValue;
                std::string StringHex = $3;
                std::stringstream ss;
                ss << std::hex << StringHex;
                ss >> ImmediateValue;
                
                
                I.mComment = "Start";
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation(EOPERATION_DELIVERCOMMAND);
                I.SetDestinationAddress( ImmediateValue+1 );
                I.SetSrc1Address( VP_COMMAND_START_MAIN_THREAD );
                mInstructions.push_back(I);
                I.Clear();
        }
        |
        SCALAR scalar_list EOS
        |
        COPY_DATA_BLOCK LESS_THAN expression COMMA expression COMMA expression GREATER_THAN EOS
        {
        
                I.SetOperation( EOPERATION_ADD );
                I.mComment = "Setting destination ID SPR for Copy data block";
                I.SetDestinationAddress( BLOCK_DST_REG );
                I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
                I.SetSrc0Address(0);
                mInstructions.push_back(I);
                I.Clear();
                
                std::cout << "COPY_DATA_BLOCK I(" << GetAddressFromIdentifier($3,yylloc) << ") " << GetAddressFromIdentifier($5,yylloc) << " " << GetAddressFromIdentifier($7,yylloc) << "\n";
                I.mComment = "Copy data block";
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation(EOPERATION_COPYBLOCK);
                //I.SetCopyDestinationId(ImmediateValue);
                I.SetCopyDestinationId(0);
                I.SetCopyDestinationAddress(GetAddressFromIdentifier($5,yylloc));
                I.SetCopySourceAddress(GetAddressFromIdentifier($7,yylloc));
                I.SetCopySize(GetAddressFromIdentifier($9,yylloc));
                mInstructions.push_back(I);
                I.Clear();
        }
        |
        EXIT EOS
        {
                //Insert a stupid NOP before the exit... is a bug but easier to just patch like this...
                
                I.mComment = "Exit";
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation(EOPERATION_EXIT);
                mInstructions.push_back(I);
                I.Clear();
        }
        
         |
         IDENTIFIER MINUS MINUS EOS
         {
                
                I.mComment = "Storing constant '1'";
                I.SetOperation( EOPERATION_SUB );
                unsigned int TmpReg  = GetFreeTempRegister(); 
                I.SetDestinationAddress( TmpReg );
                I.SetLiteral(1);
                mInstructions.push_back( I );
                I.Clear();
                
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation( EOPERATION_ADD );
                I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
                I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
                I.SetSrc0Address( TmpReg );
                mInstructions.push_back( I );
                I.Clear();
                gInsertedInstructions = 0;      
                ResetTempRegisterIndex();
         }
         |
         IDENTIFIER ADD ADD EOS
         {
         
            I.mComment = "Storing constant '1'";
                I.SetOperation( EOPERATION_ADD );
                unsigned int TmpReg  = GetFreeTempRegister(); 
                I.SetDestinationAddress( TmpReg );
                I.SetLiteral(1);
                mInstructions.push_back( I );
                I.Clear();
                
                I.mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation( EOPERATION_ADD );
                I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
                I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
                I.SetSrc0Address( TmpReg );
                mInstructions.push_back( I );
                I.Clear();
                gInsertedInstructions = 0;      
                ResetTempRegisterIndex();
        
         }
         |
         IDENTIFIER ASSIGN expression  EOS
        {
            mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation( EOPERATION_ADD );
                I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
                I.SetSrc1Address( GetAddressFromIdentifier($3,yylloc));
                I.SetSrc0Address(0);
                mInstructions.push_back( I );
                I.Clear();
                gInsertedInstructions = 0;
                ResetTempRegisterIndex();
        }
        |
        IDENTIFIER ADD ASSIGN expression EOS
        {
                mInstructions[mInstructions.size()-gInsertedInstructions].mSourceLine = GetCurrentLineNumber( yylloc );
                I.SetOperation( EOPERATION_ADD );
                I.SetDestinationAddress( GetAddressFromIdentifier($1,yylloc) );
                I.SetSrc1Address( GetAddressFromIdentifier($4,yylloc));
                I.SetSrc0Address( GetAddressFromIdentifier($1,yylloc) );
                mInstructions.push_back( I );
                I.Clear();
                gInsertedInstructions = 0;      
        }
        |
        WHILE {gWhileLoopAddress = (mInstructions.size());} OPEN_ROUND_BRACE boolean_expression CLOSE_ROUND_BRACE OPEN_BRACE statement_list CLOSE_BRACE
        {
                mInstructions[gBranchStack.back()].SetDestinationAddress(mInstructions.size()+1);
                gBranchStack.pop_back();
                //Now I need to put a GOTO so that the while gets evaluated again...
                //jump out of the if
           I.Clear();
           I.SetOperation( EOPERATION_BRANCH );
           I.mComment = "while loop goto re-eval boolean";
           I.SetDestinationAddress( gWhileLoopAddress );
           mInstructions.push_back(I);
           I.Clear();
           
           I.SetOperation( EOPERATION_NOP );
           I.mComment = "branch delay";
           I.SetDestinationAddress( gWhileLoopAddress );
           mInstructions.push_back(I);
           I.Clear();
           gInsertedInstructions = 0;
        }
        |
        START IDENTIFIER EOS
        {
                
        }
        ;
        

                         
expression
                :
                expression ADD term
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_ADD );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                        
                        //$$ = ss.str();
                        
                }
                |
                expression BITWISE_OR term
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_OR );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                }
                |
                expression MINUS term
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_SUB );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                }
                |
                term
                {
                        $$ = $1;
                }
                ;
                
                term
                :
                factor SHL factor
                {
                        
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_SHL );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                }
                |
                factor SHR factor
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_SHR );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                }
                |
                factor BITWISE_AND factor
                {
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_AND );
                        I.SetDestinationAddress( TempRegIndex );
                        I.SetSrc1Address(GetAddressFromIdentifier($1,yylloc));
                        I.SetSrc0Address(GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss;
                        ss << "R" << TempRegIndex;
                        $$ = ss.str();
                }
                |
                factor
                {
                        $$ = $1;
                }
                ;
                
                factor
                :
                IDENTIFIER
                {
                        $$ = $1;
                }
                |
                OPEN_ROUND_BRACE expression CLOSE_ROUND_BRACE
                {
                        $$ = $2;
                }
                |
                constant
                {
                        unsigned int ImmediateValue;
                        std::string StringHex = $1;
                        std::stringstream ss;
                        ss << std::hex << StringHex;
                        ss >> ImmediateValue;
                        unsigned int TempRegIndex  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_ASSIGN );
                //      I.mSourceLine = GetCurrentLineNumber( yylloc );
                        
                        I.SetDestinationAddress( TempRegIndex );
                        
                        I.SetLiteral(ImmediateValue);
                        
                        mInstructions.push_back(I);
                        
                        gInsertedInstructions++;
                        I.Clear();
                        std::stringstream ss2;
                        ss2 << "R" << TempRegIndex;
                        $$ = ss2.str();
                }
                ;
                


constant
        :
                DECCONST
                {
                        // Transform to HEX string
                        unsigned int Val;
                        std::string StringDec = $1;
                        std::stringstream ss;
                        ss << StringDec;
                        ss >> Val;
                        std::stringstream ss2;
                        ss2 << std::hex << Val;
                        $$ = ss2.str();
                }
                |
                HEXCONST
                {
                        std::string StringHex = $1;
                        // Get rid of the 0x
                        StringHex.erase(StringHex.begin(),StringHex.begin()+2);
                        std::stringstream ss;
                        ss << std::hex << StringHex;
                        
                        $$ = ss.str();
                }
                |
                BINCONST
                {
                        // Transform to HEX string
                        std::string StringBin = $1;
                        // Get rid of the 0b
                        StringBin.erase(StringBin.begin(),StringBin.begin()+2);
                        std::bitset<32> Bitset( StringBin );
                        std::stringstream ss2;
                        ss2 << std::hex <<  Bitset;
                        $$ = ss2.str();
                }
        ;
        
boolean_expression
        :
        BLOCK_TRANSFER_IN_PROGRESS
        {
        
                        unsigned int ImmediateValue = 0x1; 
                        unsigned int TempRegIndex0  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_ASSIGN );
                        I.SetDestinationAddress( TempRegIndex0 );
                        I.SetLiteral(ImmediateValue);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
        
                        
                        I.SetOperation( EOPERATION_BEQ );
                        I.SetDestinationAddress( 0 );
                        I.SetSrc1Address( STATUS_REG );
                        I.SetSrc0Address(TempRegIndex0);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        gBranchStack.push_back(mInstructions.size() - 1);
                        I.Clear();
                        
                        I.SetOperation( EOPERATION_NOP );
                        I.mComment = "branch delay";
                        I.SetDestinationAddress( gWhileLoopAddress );
                        mInstructions.push_back(I);
                        I.Clear();
                        
                        
                
        }
        |
        expression EQUAL expression
        {
                        
                        I.SetOperation( EOPERATION_BNE );
                        I.SetDestinationAddress( 0 );
                        I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
                        I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        gBranchStack.push_back(mInstructions.size() - 1);
                        I.Clear();
                        
                        I.SetOperation( EOPERATION_NOP );
                        I.mComment = "branch delay";
                        I.SetDestinationAddress( gWhileLoopAddress );
                        mInstructions.push_back(I);
                        I.Clear();
                        
        }
        |
        expression LESS_OR_EQUAL_THAN expression
        {
                        
                        I.SetOperation( EOPERATION_BLE );
                        I.SetDestinationAddress( 0 );
                        I.SetSrc1Address( GetAddressFromIdentifier($1,yylloc) );
                        I.SetSrc0Address( GetAddressFromIdentifier($3,yylloc));
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        gBranchStack.push_back(mInstructions.size() - 1);
                        I.Clear();
                        
                        I.SetOperation( EOPERATION_NOP );
                        I.mComment = "branch delay";
                        I.SetDestinationAddress( gWhileLoopAddress );
                        mInstructions.push_back(I);
                        I.Clear();
                        
        }
        |
        constant 
        {
                        unsigned int ImmediateValue;
                        std::string StringHex = $1;
                        std::stringstream ss;
                        ss << std::hex << StringHex;
                        ss >> ImmediateValue;                   
                        unsigned int TempRegIndex0  = GetFreeTempRegister();
                        I.SetOperation( EOPERATION_ASSIGN );
                        I.SetDestinationAddress( TempRegIndex0 );
                        I.SetLiteral(ImmediateValue);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
        
                        
                        I.SetOperation( EOPERATION_BEQ );
                        I.SetDestinationAddress( 0 );
                        I.SetSrc1Address( 0 );                                  //Compare againts zero
                        I.SetSrc0Address(TempRegIndex0);
                        mInstructions.push_back(I);
                        gInsertedInstructions++;
                        gBranchStack.push_back(mInstructions.size() - 1);
                        I.Clear();
                        
                        I.SetOperation( EOPERATION_NOP );
                        I.mComment = "branch delay";
                        I.SetDestinationAddress( gWhileLoopAddress );
                        mInstructions.push_back(I);
                        I.Clear();
        }
;       
scalar_list
                        :
                        IDENTIFIER COMMA scalar_list
                        {
                                if (gVaribleMap.find($1) != gVaribleMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol '" << $1 << "'\n";
                                        throw ret.str();
                                }
                        
                                gVaribleMap[ $1 ] = AllocateVariable();
                        }
                        |
                        IDENTIFIER ASSIGN constant COMMA scalar_list
                        {
                                if (gVaribleMap.find($1) != gVaribleMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol '" << $1 << "'\n";
                                        throw ret.str();
                                }
                        
                                gVaribleMap[ $1 ] = AllocateVariable();
                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                I.SetOperation( EOPERATION_ASSIGN );
                                I.SetDestinationAddress( gVaribleMap[ $1 ] );
                                I.SetLiteral( atoi($3.c_str() ) );
                                mInstructions.push_back( I );
                                I.Clear();
                                
                        }
                        |
                        IDENTIFIER ASSIGN constant
                        {
                                if (gVaribleMap.find($1) != gVaribleMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol '" << $1 << "'\n";
                                        throw ret.str();
                                }
                                unsigned int ImmediateValue;
                                std::string StringHex = $3;
                                std::stringstream ss;
                                ss << std::hex << StringHex;
                                ss >> ImmediateValue;
                                gVaribleMap[ $1 ] = AllocateVariable();
                                I.mSourceLine = GetCurrentLineNumber( yylloc );
                                I.SetOperation( EOPERATION_ASSIGN );
                                I.SetDestinationAddress( gVaribleMap[ $1 ] );
                                I.SetLiteral( ImmediateValue );
                                mInstructions.push_back( I );
                                I.Clear();
                        }
                        |
                        IDENTIFIER  
                        {
                                if (gVaribleMap.find($1) != gVaribleMap.end())
                                {
                                        std::ostringstream ret;
                                        ret << "Duplicated symbol '" << $1 << "'\n";
                                        throw ret.str();
                                }
                        
                                gVaribleMap[ $1 ] = AllocateVariable();
                        }
                        ;


%%



// Error function throws an exception (std::string) with the location and error message
void Theia::Parser::error(const Theia::Parser::location_type &loc,
                                          const std::string &msg) {
        std::ostringstream ret;
        ret << "\ncp_compile -- Parser Error at " << loc << ": "  << msg;
        throw ret.str();
}

// Now that we have the Parser declared, we can declare the Scanner and implement
// the yylex function
#include "Scanner.h"
static int yylex(Theia::Parser::semantic_type * yylval,
                 Theia::Parser::location_type * yylloc,
                 Theia::Scanner &scanner) {
        return scanner.yylex(yylval, yylloc);
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.