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

Subversion Repositories yacc

[/] [yacc/] [trunk/] [bench/] [c_src/] [calculator/] [uart_echo_test.c] - Rev 4

Compare with Previous | Blame | View Log

//Apr.4.2005 Rewritten for RAM16K and Engilish
//RTL Simulation use Only 
//By using uart echo technique, UART interrupt routine and h/w are checked.
//YACC Project on CYCLONE 4KRAM
//Jul.15.2004 Simple 32bit calculator
// 
 
 
#define print_port 0x3ff0
#define print_char_port 0x3ff1
#define print_int_port 0x3ff2
#define print_long_port 0x3ff4
 
 
#define uart_port		0x03ffc //for 16KRAM
#define uart_wport uart_port
#define uart_rport uart_port
#define int_set_address 0x03ff8 //for 16KRAM
 
 
 
#define BUFFER_SIZE 120
unsigned char * read_ptr;
char buffer[BUFFER_SIZE];//
char result_buffer[8];//8+1
unsigned char sym;
unsigned char* char_ptr;
long term(void);
long factor(void);
long expression(void);
void calculator();
int volatile int_flag=0;//volatile is must. Without it,No calculation will be done because of Compiler Optimization.
char buf[2];
#define DEBUG //For RTL Simulation USE
void print_uart(unsigned char* ptr)// 
{
	#define WRITE_BUSY 0x0100
	unsigned uport;
	while (*ptr) {
		do {
		  uport=*(volatile unsigned*)	uart_port;
		} while (uport & WRITE_BUSY);
		*(volatile unsigned char*)uart_wport=*(ptr++);
	}
}	
 
 
void putc_uart(unsigned char c)// 
{
	unsigned uport;
 
	do {
		  uport=*(volatile unsigned*)	uart_port;
	} while (uport & WRITE_BUSY);
 
	*(volatile unsigned char*)uart_wport=c;
}	
 
void print_char(unsigned char val)// 
{
	#ifdef DOS
		printf("%x ",val);
	#else
	*(volatile unsigned char*)print_char_port=(unsigned char)val ;
	#endif
 
}
unsigned char read_uart()//Apr.4.2005 changed 32 bits port
{
	unsigned uport=*(volatile unsigned*)uart_port;
//	print_char(uport);
		return uport;
}	
 
void print(unsigned char* ptr)//Verilog Test Bench Use 
{
	#ifdef DOS
			printf("%s ",ptr); 
	#else
 
	while (*ptr) {
 
		*(volatile unsigned char*)print_port=*(ptr++);
	}
 
	*(volatile unsigned char*)print_port=0x00;//Write Done
	#endif
}
 
void print_short(short val)//Little Endian write out 16bit number 
{	
	#ifdef DOS
		printf("%x",val);
	#else
		*(volatile unsigned short*)print_int_port=val ;
	#endif
 
 
}
 
void print_long(unsigned long val)//Little Endian write out 32bit number 
{
	#ifdef DOS
			printf("%x",val);
	#else
			*(volatile unsigned long*)print_long_port=val;
 
	#endif
 
}
 
 
//Interrupt Service Routine.
//If 0D/0A comes then, 
//{write 0 at the end of buffer.
// Parse Analysis by hand,
//}else increment READ_PTR
//if Overflow MessageOUT
 void interrupt(void)
{
	char c;
#define SAVE_REGISTERS   (13*4)
	asm("addiu	$sp,$sp,-52 ;");//SAVE_REGISTERS
 
	asm("	sw	$a0,($sp)");//Save registers@
	asm("	sw  $v0,4($sp)");
	asm("	sw  $v1,8($sp)");
	asm("	sw  $a1,12($sp)");
	asm("	sw  $s0,16($sp)");
	asm("	sw  $s1,20($sp)");
	asm("	sw  $s2,24($sp)");
 
	asm("	sw  $a3,28($sp)");
	asm("	sw  $s4,32($sp)");
	asm("	sw  $s5,36($sp)");
	asm("	sw  $s6,40($sp)");
	asm("	sw  $s7,44($sp)");
	asm("	sw  $a2,48($sp)");
 
 
 
	c=read_uart();//read 1Byte from uart read port.
 
 
	if ( c == 0x0a || c==0x0d )
	{
			*read_ptr = 0;//string end
			read_ptr=buffer;//Initialization of read_ptr
 
 
				putc_uart(0x0a);	
				putc_uart(0x0d);
 
			if (int_flag) print("PError!\n");
			else		int_flag=1;
 
	}  else if ( c == '\b' && read_ptr > buffer ){//Backspace
 
				putc_uart('\b');
 
 
			read_ptr--;
	}else if ( read_ptr>= buffer+BUFFER_SIZE){// overflow
		//
	 		*read_ptr = 0;//string end
			read_ptr=buffer;//Initialization of read_ptr
			print_uart("Sorry Overflow..!\n");
 
	}else {//post increment
 
				putc_uart(c);
 
			*(read_ptr++) = c;
	}
 
#ifdef DEBUG
//	print(buffer);
//	print("\n\n");
#endif	
 
//Restore Saved Registers.
 
	asm("	lw	$a0,($sp)");
	asm("	lw  $v0,4($sp)");
	asm("	lw  $v1,8($sp)");
	asm("	lw  $a1,12($sp)");
	asm("	lw  $s0,16($sp)");
	asm("	lw  $s1,20($sp)");
	asm("	lw  $s2,24($sp)");
 
	asm("	lw  $a3,28($sp)");
	asm("	lw  $s4,32($sp)");
	asm("	lw  $s5,36($sp)");
	asm("	lw  $s6,40($sp)");
	asm("	lw  $s7,44($sp)");
	asm("	lw  $a2,48($sp)");
 
	asm("addiu	$sp,$sp,52 ;");//SAVE_REGISTERS
							//Adjust! 
	asm("lw	$ra,20($sp);");//Adjust! See dis-assemble list
	asm("addiu	$sp,$sp,24 ;");//Adjust.
    asm("jr	$26");//Return Interrupt
	asm("nop");//Delayed Slot
//
 
}	
 
inline void set_interrupt_address()
{
	*(volatile unsigned long*)int_set_address=(unsigned long)interrupt;
	read_ptr=buffer;	
}
 
 
void print_longlong(long long val)//Little Endian write out 32bit number 
{
	#ifdef DOS
			printf("%x",val);
	#else
			*(volatile unsigned long*)print_long_port=val>>32;
			*(volatile unsigned long*)print_long_port=val;
 
	#endif
 
}
 
 
 void getsym()
{
 
 
	while ( *char_ptr==' ' || 
			*char_ptr=='\n' ||
			*char_ptr=='\r' ) char_ptr++;
	if (*char_ptr ==0) {
		sym=0;	
	}else {
		sym=*(char_ptr++);
 
	}		
}
 
inline void init_parser()
{
	char_ptr=buffer;
	getsym();
 
}
 
 
long evaluate_number(void)
{
 
	long x ;
 
	x=sym-'0';
	while(*char_ptr >='0' && *char_ptr <='9') {
		x = x * 10 + *char_ptr - '0';
		char_ptr++;
	}
	getsym();
 
	return x;
}
long expression(void)
{
	long term1,term2;
	unsigned char op;
 
	op=sym;
 
	if (sym=='+' || sym=='-') getsym();
	term1=term();
 
	if (op=='-') term1=-term1;
 
	while (sym=='+' || sym=='-') {
		op=sym;
		getsym();
		term2=term();
		if (op=='+') term1= term1+term2;
		else 		  term1= term1-term2;
	}
 
	return term1;		
}
 
long term(void)
{
	unsigned char op;
	long factor1,factor2;
 
	factor1=factor();
	while ( sym=='*' || sym=='/' || sym=='%'){
		op=sym;
		getsym();
		factor2=factor();
 
		switch (op) {	
			case '*': factor1= factor1*factor2;
					  break;
			case '/': factor1= factor1/factor2;
					  break;
			case '%':   factor1= factor1%factor2;
					  break;
		}
	}
 
	return factor1;
}
 
inline long parse_error()
{
	print_uart("\n parse error occurred\n");
	return 0;	
}	
 
long factor(void)
{
	int i;
 
	if (sym>='0' && sym <='9')	 return evaluate_number();
	else if (sym=='('){
 
					getsym();
					i= expression();
 
					if (sym !=')'){
						parse_error();
					} 
					getsym();
					return i;	 
	}else  if (sym==0) return 0;
	else return parse_error();			 	
}
 
 
 
 
 
char *strrev(char *s) {
	char *ret = s;
	char *t = s;
	char c;
 
	while( *t != '\0' )t++;
	t--;
 
	while(t > s) {
		c = *s;
		*s = *t;
		*t = c;
		s++;
		t--;
	}
 
	return ret;
}
 
 
void itoa(int val, char *s) {
	char *t;
	int mod;
 
	if(val < 0) {
		*s++ = '-';
		val = -val;
	}
	t = s;
 
	while(val) {
		mod = val % 10;
		*t++ = (char)mod + '0';
		val /= 10;
 
	}
 
	if(s == t)
		*t++ = '0';
 
	*t = '\0';
 
 
	strrev(s);
}
void calculator()
{
	long result;
 
//Parser Initialization	
	init_parser();
 
//Calculation
	result=expression();
 
//	
	#ifdef DEBUG
	print("\n");
	print(buffer);
	print("=");
	print_long(result);
	print("[Hex]   ");
	itoa(result,result_buffer);
	print(result_buffer);
	print("[Dec]\n");
 
	#else
	print_uart(buffer);
	putc_uart('=');
	print_uart(result_buffer);
	putc_uart(0x0a);
	putc_uart(0x0a);	
	putc_uart(0x0d);	
 
	#endif	
 
 
}	
 
void strcpy(char* dest,char* source)
{
 
	char* dest_ptr;
	dest_ptr=dest;	
 
	while(*source) {
 
		*(dest++) =*(source++);	
	} ;
 
	*dest=0;//Write Done
 
 
}	
void calculator_test(char* ptr)
{
	strcpy(buffer,ptr);
	calculator();
 
}	
 
void main()
{
	unsigned counter=0;
 
 
	set_interrupt_address();//Set Interrupt Service Address
 
    print_uart("5*3\n");//Send UART PORT TXD, then echo backed to RXD in verilog test bench.
	print_uart("100*31\n");//Don't care overflow,Altera Imprementation has UART FIFO 512bytes
	print_uart("(-31050)/(-31)\n");
	print_uart("(-1053333)/(231)\n");
    print_uart("(10503)/(-314)\n");
    print_uart("3333*3333\n");
 	print_uart("533*443\n");
	print_uart("10*314\n");
	print_uart("(-350)/(-231)\n");
	print_uart("(-10533333)/(1231)\n");
    print_uart("(105034)/(-3134)\n");
    print_uart("3363*33333\n");
	label:
	if (int_flag){//if interrupt service routine reports end of string,
			int_flag=0;
			calculator();//then parse the string,calculates, and report the result to debug port.
			counter++;
			if (counter>=12) 	print("$finish");
	}	
	goto label;
 
}	
 

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.