原创 My first compiler - using flex

2008-12-8 18:27 3010 3 3 分类: FPGA/CPLD
Question: I write a address generater, which use micro code to generate address. For generating the micro codes easily, I create a some symbols and syntax to descrbie the micro code, things like assembly languange, as following:

/*
JDNZ  Rx LABEL; {[0],[LABLE],[xx]}      # x = 4~7, LABEL is 5 bits. If Rx equals 0, load Rx to initial value and
                                        # execute next code by increase PC by 1. Otherwise, jump to LABEL to and
                                        # run;
ADDR0 #;        {[10],[######]}         # add constant to R0. constant is 1~64.
SWAPR Rm Rn;    {[1100],[mm],[nn]}      # swap Rm and Rn, m and n are from 0 to 3
RST;            {[11010],[xxx]}         # reset all R to initial value
NU;             {[11011],[xxx]}         # addr is not usable, that means give the ack signal to data interface but
                                        # the input data will not be saved to the internal ram.
ADD   Rx;       {[11100],[xxx]}         # addr Rx to addr.
INCLD Rx;       {[11101],[xxx]}         # load Rx to addr, then increase Rx by 1       
LD    Rx;       {[11110],[xxx]}         # load Rx to addr
RSTR  Rx;       {[11111],[xxx]}         # reset Rx to initial value
*/
// this is a comment line
// Define rbus index address and data address
INDEX    =    JCD_TBL_INDEX;
DATA    =    JCD_TBL_DATA;

  init  {
    R0 = 0;    //set the init value of Rx
    R1 = 64;
    R2 = 256;
    R3 = 256;
    R4 = 64;
    R5 = 4;
    R6 = 8;
    R7 = 2;
  }   

program  {
lbl0:
    INCLD R0;
    LD R2;
    ADD R4;
    INCLD R0;
    INCLD R2;
    ADD R4;
    JDNZ R5 lbl0;
    SWAPR R0 R1;
lbl1:
    INCLD R0;
    LD R2;
    ADD R4;
    INCLD R0;
    INCLD R2;
    ADD R4;
    JDNZ R5 lbl1;
    SWAPR R0 R1;
    SWAPR R2 R3;

    JDNZ R6 lbl0;

    ADDR0 #64;
    SWAPR R0     R1;
    ADDR0 #64;
    SWAPR R0  R1;

    JDNZ R7 lbl0      ;
   
    RST;
}


The init part inside "{" and "}" means how to initialize the R0~R7 registers. The program part inside "{" and "}" means micro code to generate the address. And INDEX is the configure register for index, DATA is the configure register for data.

Now, I need a compiler to convert the these "assembly" to appropriate micro code.
The expected output is like "RBUS[JCD_TBL_INDEX] = XXX;" or "RBUS[JCD_TBL_DATA] = XXX", which are use for C language.

Then I use flex to help me generate the pattern scanner and make the compiler works. The Flex file named compjcd.l is as following:

%{
//=======================================
// Compile the address generation code
// into binary micro code. Please Refer
// example, dec411.
//=======================================
#include <stdio.h>

int bFindInit=0, bFindProg=0;
int bFindLabel=0;
int bErr = 0;
int iPC=0;
int iLabel=0;
int aLabelPC[8];
char sLabel[8][64] = {"\0", "\0", "\0", "\0"} ;
char sBuff[64];
char sIndex[32], sData[32];
char PC[32];
int iTmp, iTmp2;
int i;
int condition;
%}

%option yylineno
%x COMMENT
%s INIT PROG

chars    [A-Za-z\_]
numbers    ([0-9])+
hex    0x([0-9])+
alpha     [0-9A-Za-z]
words    {chars}+({numbers}|{chars})*
sp    [\t ]
%%

"INDEX"{sp}*"="{sp}*({numbers}|{hex}|{words})+{sp}*";"    {    // find INDEX define
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = '\0';
        i = 5;
        while(*(yytext+i) != '=') // search '='
            i++;
       
        sscanf(yytext+i+1, "%s", sIndex);
        //printf("%s\n", sIndex);
    }

"DATA"{sp}*"="{sp}*({numbers}|{hex}|{words})+{sp}*";"    {    // find DATA define
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = '\0';
        i = 4;
        while(*(yytext+i) != '=') // search '='
            i++;
       
        sscanf(yytext+i+1, "%s", sData);
        //printf("%s\n", sData);
    }
       
"init"{sp}*"{"    {
        //printf("[I]@%d: Find \"init\".\n", yylineno);
        printf("//Initialize R0~R7\n");
        bFindInit=1;   
        BEGIN( INIT );
    }

<INIT>"}"    BEGIN( 0 );


<INIT>"R"[0-7]{1}{sp}*"="{sp}*({numbers}|{hex}){sp}*";"        {
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = '\0';
        iTmp = atoi(yytext+1);
        //printf("%d\n", iTmp);
        i = 2;
        while(*(yytext+i) != '=')    // search '='
            i++;
        sscanf(yytext+i+1, "%d", &iTmp2);
        iTmp *= 2; iTmp += 32;
        printf("RBUS[%s]=0x%02X;\n", sIndex, iTmp);
        printf("RBUS[%s]=0x%02X;\n", sData, iTmp2&0xff);
        iTmp++;
        printf("RBUS[%s]=0x%02X;\n", sIndex, iTmp);
        printf("RBUS[%s]=0x%02X;\n", sData, (iTmp2>>8)&0xff);
    }

"program"{sp}*"{" {
        //printf("[I]@%d: Find \"program\".\n", yylineno);
        printf("//Configure program\n");
        printf("RBUS[%s]=0x00;\n", sIndex);
        iPC=0;
        bFindProg=1;
        BEGIN( PROG );
    }

<PROG>"}"    BEGIN( 0 );

    /* find label */
<PROG>{chars}+{numbers}*":"    {
        aLabelPC[iLabel]=iPC;
        *(yytext+yyleng-1)='\0';
        //printf("[I]@%d: Find label: %s, number: %d\n", yylineno, yytext, iLabel);
        strcpy(sLabel[iLabel], yytext);
        iLabel++;
    }

    /* JDNZ */
<PROG>"JDNZ"{sp}+"R"[0-7]{1}{sp}+{words}{sp}*";"    {
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = ' ';
        i=4;
        while(*(yytext+i)!='R') {
            i++;
        }
        iTmp = atoi(yytext+i+1);
        //printf("%d\n", iTmp);
        if(iTmp < 4)    {
            bErr = 1;
            printf("[E]@%d: JDNZ: Evaluated register must be one of R4 to R7.\n", yylineno, yytext);
        }
        else
            iTmp -= 4;
        sscanf((yytext+i+2), "%s", sBuff);
        //printf("%s\n", sBuff);
        for(i=0; i<4; i++)
        {
            //printf("%s\n", sLabel);
            if(strcmp(sBuff, sLabel)==0) {
                iTmp = iTmp+(aLabelPC<<2);
                bFindLabel = 1;
            }
        }
        if(bFindLabel)    {
            printf("RBUS[%s]=0x%02X;", sData, iTmp);
            PC[iPC] = iTmp&0xFF;
            iPC++;
        }
        else {
            bErr = 1;
            printf("[E]@%d: JDNZ syntax error, jump label is not found.\n", yylineno);
        }
    }
<PROG>"JDNZ"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: JDNZ syntax error.\n", yylineno);
    }

    /* ADDR0 */
<PROG>"ADDR0"{sp}+"#"({numbers}|{hex}){sp}*";"    {
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = '\0';
        i = 5;
        while(*(yytext+i) != '#')
            i++;
        iTmp = atoi(yytext+i+1);
        //printf("%d\n", iTmp);
        if( (iTmp<1) || (iTmp>64) )    {
            bErr = 1;
            printf("[E]@%d: ADDR0 syntax error, constant must be value from 1 to 64.\n", yylineno);
        }
        else    {
            PC[iPC] = ((0x02<<6)+iTmp-1)&0xff;
            printf("RBUS[%s]=0x%02X;\n", sData, (0x02<<6)+iTmp-1);
            iPC++;
        }
    }
<PROG>"ADDR0"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: ADDR0 syntax error.\n", yylineno);
    }

    /* SWAPR */
<PROG>"SWAPR"{sp}+"R"[0-3]{1}{sp}+"R"[0-3]{1}{sp}*";"    {
        //printf("%s\n", yytext);
        *(yytext+yyleng-1) = '\0';
        iTmp=0;
        for(i=5; i<yyleng; i++) {
            if(*(yytext+i)=='R')
                iTmp = (iTmp<<2) + atoi(yytext+i+1);
        }
        PC[iPC] = ((0x0C<<4)+iTmp)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x0C<<4)+iTmp);
        iPC++;
    }
<PROG>"SWAPR"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: SWAPR syntax error.\n", yylineno);
    }

    /* RST */
<PROG>"RST"{sp}*";"    {
        //printf("%s\n", yytext);
        PC[iPC] = (0x1A<<3)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1A<<3));
        iPC++;
    }
<PROG>"RST"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: RST syntax error.\n", yylineno);
    }

    /* NG */
<PROG>"NG"{sp}*";"    {
        //printf("%s\n", yytext);
        PC[iPC] = (0x1B<<3)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1B<<3));
        iPC++;
    }
<PROG>"NG"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: NG syntax error.\n", yylineno);
    }

    /* ADD */
<PROG>"ADD"{sp}+"R"[0-7]{1}{sp}*";"    {
        //printf("%s\n", yytext);
        i=3;
        while(*(yytext+i) != 'R')
            i++;
        iTmp=atoi(yytext+i+1);

        PC[iPC] = ((0x1C<<3)+iTmp)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1C<<3)+iTmp);
        iPC++;
    }
<PROG>"ADD"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: ADD syntax error.\n", yylineno);
    }

    /* INCLD */
<PROG>"INCLD"{sp}+"R"[0-7]{1}{sp}*";"    {
        //printf("%s\n", yytext);
        i=5;
        while(*(yytext+i) != 'R')
            i++;
        iTmp=atoi(yytext+i+1);
        PC[iPC] = ((0x1D<<3)+iTmp)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1D<<3)+iTmp);
        iPC++;
    }
<PROG>"INCLD"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: INCLD syntax error.\n", yylineno);
    }

    /* LD */
<PROG>"LD"{sp}+"R"[0-7]{1}{sp}*";"    {
        //printf("%s\n", yytext);
        i=2;
        while(*(yytext+i) != 'R')
            i++;
        iTmp=atoi(yytext+i+1);
        PC[iPC] = ((0x1E<<3)+iTmp)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1E<<3)+iTmp);
        iPC++;
    }
<PROG>"LD"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: LD syntax error.\n", yylineno);
    }

    /* RSTR */
<PROG>"RSTR"{sp}+"R"[0-7]{1}{sp}*";"    {
        //printf("%s\n", yytext);
        i=4;
        while(*(yytext+i) != 'R')
            i++;
        iTmp=atoi(yytext+i+1);
        PC[iPC] = ((0x1F<<3)+iTmp)&0xff;
        printf("RBUS[%s]=0x%02X;\n", sData, (0x1F<<2)+iTmp);
        iPC++;
    }

<PROG>"RSTR"{sp}+.    {
        bErr = 1;
        printf("[E]@%d: RSTR syntax error.\n", yylineno);
    }

    /* Line Comment */
"//"[^\n]*   

    /* Block Comment */
"/*"    BEGIN( COMMENT );
<COMMENT>.    /* output nothing when comment */
<COMMENT>"*"+"/"    BEGIN( 0 );

{words}+{sp}*";"    {
        bErr = 1;
        printf("[E]@%d: Unknown code: %s.\n", yylineno, yytext);
    }

{words}        {
        bErr = 1;
        printf("[E]@%d: %s is unknown. Maybe \";\" is missing at end of line.\n", yylineno, yytext);
    }

.        /* outout nothing when other alphas */

<<EOF>>    {
        if(bFindInit==0)
        {
            bErr = 1;
            printf("[E] 0: init part is not found!");
        }
        if(bFindProg==0)
        {
            bErr = 1;
            printf("[E] 1: program part is not found!");
        }
        return 0;
    }
%%

int main(argc, argv)
int argc;
char **argv;
{
    FILE* hFileOut;
    for(i=0; i<32; i++)
    {
        PC = 0;
    }
    yylex();
    return 0;
}

int yywrap()
{
    return 1;
}

Then, generate the compiler:
 $flex compjcd.l



PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
3
关闭 站长推荐上一条 /3 下一条