tab2vmem_gram.y 6.55 KB
/* tab2vmem_gram.y - Grammar for tab2vmem  */


%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <values.h>

#include "tab2vmem.h"

/*
 * tokenString is global holding last ident, string, literal
 * shorn of quotes
 */

#define TOKENSIZ  	256
#define MAX_NUMBER_LEN  128

typedef union _NameType {
   char name[TOKENSIZ];
   int  ival;
} NameType;

#define YYSTYPE NameType

/* Forward References */

void    install(char *);
void    install_number(char *, int);


/* globals */

extern FILE *Vecfp; /* memory vectors */

SigDef Signal[MAX_SIGNALS];
ClockDef Clock[MAX_CLOCKS];
int nSigs = 0;  /* number of signals */
int nClocks = 0;  /* number of signals */
int nVecs = 0;  /* number of vectors */
int MemWidth = 0;  /* test vector memory width in bits */

static char VecArray[MAX_SIGNALS][MAX_NUMBER_LEN];
static int CurSig    = 0; /* current signal */
static int CurEdge   = 0; /* current edge timing */
static int CurStrobe = 0; /* current strobe timing */
static int ClkSig = 0; /* clock signal flag */
static int ClkPhase = 0; /* clock phase count */
static int line_num = 0;
static int VectorPhase = 0;

%}

%start Input

/* Reserved Keywords */


/* symbols */

%token tCOLON
%token tEOL
%token tLBRACK
%token tRBRACK
%token tLPAREN
%token tRPAREN
%token tPERCENT
%token tQUOTE
%token tINPUT
%token tOUTPUT
%token tBIDIR
%token tTRI
%token tEDGE
%token tSTROBE
%token tCLOCK
%token tVALID

/* patterns */

%token tNUMBER
%token tHEX
%token tIDENT
%token tJUNK

%%

Input		: /* EMPTY */
		| Input Statement
;

Statement	: tEOL
		{
		  VectorPhase = 1;
		}
		| Signals tEOL
		{
		  if(!ClkSig)
		    nSigs++;
		  else {
		    ClkSig = 0;
		    nClocks++;
		  }
		  if(nSigs > MAX_SIGNALS)
		  {
		    fprintf(stderr,"ERROR: number of signals exceeds max(%d)\n", MAX_SIGNALS);
		    exit(911);
		  }
		  if(nClocks > MAX_CLOCKS)
		  {
		    fprintf(stderr,"ERROR: number of clocks exceeds max(%d)\n", MAX_CLOCKS);
		    exit(911);
		  }
		}
		| Vector tEOL
		{
		  int i;
		  /* do some consistency checks between header and vectors on first vector */
		  if(nVecs == 0)
		  {
		    if(CurSig != nSigs)
		    {
		      fprintf(stderr,"ERROR: number of signals in header(%d) doesn't match number of vectors(%d)\n", nSigs, CurSig);
		      exit(911);
		    }
		    for(i = 0; i < nSigs; i++)
		    {
		      if((Signal[i].hex_dig && (strlen(VecArray[i]) != Signal[i].hex_dig)) ||
			 (!Signal[i].hex_dig && (strlen(VecArray[i]) != 1)))
		      {
			fprintf(stderr,"ERROR: length(%d) of vector field %d doesn't match signal definition(%d)\n",
			  strlen(VecArray[i]), i, Signal[i].hex_dig ? Signal[i].hex_dig : 1);
  		        exit(911);
		      }
		    }
		  }
	
		  /* print vectors */
		  for(i = 0; i < nSigs; i++) 
		  {
		    fprintf(Vecfp,"%s_", VecArray[i]);
		  }
		  fprintf(Vecfp, "\n");
		  CurSig = 0; /* reset */
		  nVecs++;
		}
;

		  	
Signals		: InputSig
		| OutputSig
		| BiDirectionalSig
		| ValidSig
		| ClockSig
		{
		  ClkSig = 1;
		}
		| error
		{
		  printf("Signal, Unrecognized signal syntax: %s\n", yylval.name);
		}
;

InputSig	: SignalName tINPUT
                {
                  Signal[nSigs].type = VMEM_INPUT;
                }
		| InputSig tEDGE tNUMBER
		{
		  Signal[nSigs].edge = $3.ival;
		  CurEdge = $3.ival;
		}
		| InputSig tVALID tIDENT
		{
		  strcpy(Signal[nSigs].val_sig_name, $3.name);
		  strcat(Signal[nSigs].val_sig_name, "_v");
		  Signal[nSigs].valid = 1;
		}
;

OutputSig	: SignalName tOUTPUT
                {
                  Signal[nSigs].type = VMEM_OUTPUT;
                }
		| OutputSig tSTROBE tNUMBER
		{
		  Signal[nSigs].strobe = $3.ival;
		  CurStrobe = $3.ival;
		}
		| OutputSig tVALID tIDENT
		{
		  strcpy(Signal[nSigs].val_sig_name, $3.name);
		  strcat(Signal[nSigs].val_sig_name, "_v");
		  Signal[nSigs].valid = 1;
		}
;

BiDirectionalSig: SignalName tBIDIR tIDENT tNUMBER
                {
                  strcpy(Signal[nSigs].en_sig_name, $3.name);
                  Signal[nSigs].type = VMEM_BIDIR;
                  Signal[nSigs].polarity = $4.ival;
                }
		| BiDirectionalSig tEDGE tNUMBER
		{
		  Signal[nSigs].edge = $3.ival;
		  CurEdge = $3.ival;
		}
		| BiDirectionalSig tSTROBE tNUMBER
		{
		  Signal[nSigs].strobe = $3.ival;
		  CurStrobe = $3.ival;
		}
		| BiDirectionalSig tVALID tIDENT
		{
		  strcpy(Signal[nSigs].val_sig_name, $3.name);
		  strcat(Signal[nSigs].val_sig_name, "_v");
		  Signal[nSigs].valid = 1;
		}
;

ValidSig	: SignalName tVALID
                {
                  strcat(Signal[nSigs].sig_name, "_v");
                  Signal[nSigs].type = VMEM_VALID;
                }
		| ValidSig tEDGE tNUMBER
		{
		  Signal[nSigs].edge = $3.ival;
		  CurEdge = $3.ival;
		}
;

ClockSig	: SignalName tCLOCK tNUMBER tLPAREN tNUMBER tRPAREN
		{
		  /* copy signal name, don't increment signals */
		  strcpy(Clock[nClocks].sig_name, Signal[nSigs].sig_name);
		  ClkPhase = 0;
		  Clock[nClocks].val[ClkPhase] = $3.ival;
		  Clock[nClocks].time[ClkPhase] = $5.ival;
		  ClkPhase++;
		  Clock[nClocks].phases = ClkPhase;
		}
		| ClockSig tNUMBER tLPAREN tNUMBER tRPAREN
		{
		  /* copy signal name, don't increment signals */
		  if(ClkPhase > MAX_CLK_PHASES) {
		    fprintf(stderr,"Error, exceeded max number of clk phases %d\n",
		   	ClkPhase);
		    exit(911);
		  }
		  Clock[nClocks].val[ClkPhase] = $3.ival;
		  Clock[nClocks].time[ClkPhase] = $5.ival;
		  ClkPhase++;
		  Clock[nClocks].phases = ClkPhase;
		}
;

SignalName	: Bus
		{
		  Signal[nSigs].type    = VMEM_INPUT; /* default */
		  Signal[nSigs].edge    = CurEdge; /* default */
		  Signal[nSigs].strobe  = CurStrobe; /* default */
		  Signal[nSigs].valid = 0;
		  MemWidth += Signal[nSigs].hex_dig * 4;
		}
		| tIDENT
		{
		  strcpy(Signal[nSigs].sig_name, $1.name);
		  Signal[nSigs].size    = 1;
		  Signal[nSigs].msb     = 0;
		  Signal[nSigs].lsb     = 0;
		  Signal[nSigs].hex_dig = 0;
		  Signal[nSigs].type    = VMEM_INPUT; /* default */
		  Signal[nSigs].edge    = CurEdge; /* default */
		  Signal[nSigs].strobe  = CurStrobe; /* default */
		  Signal[nSigs].valid = 0;
		  MemWidth += 4;
		}
;


Bus		: tIDENT tLBRACK tNUMBER tCOLON tNUMBER tRBRACK
		{
		  sprintf(Signal[nSigs].sig_name, "%s\0",$1.name);
		  Signal[nSigs].msb     = $3.ival;
		  Signal[nSigs].lsb     = $5.ival;
		  Signal[nSigs].size    = $3.ival - $5.ival + 1;
		  Signal[nSigs].hex_dig = (Signal[nSigs].size + 3) / 4;
		}
;

Vector		: VecNumber
		| Vector VecNumber
		| error
		{
		  printf("Unrecognized signal syntax: %s\n", yylval.name);
		}
;

VecNumber	: tNUMBER
		{
		  strcpy(VecArray[CurSig++],$1.name);
		}
		| tHEX
		{
		  strcpy(VecArray[CurSig++],&($1.name[2]));
		}
;


%%

#include "tab2vmem_scan.c"