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

Subversion Repositories yac

[/] [yac/] [trunk/] [test_sys/] [sw/] [pc/] [main.c] - Rev 11

Compare with Previous | Blame | View Log

/***************************************************************************
*                                                                          *
*  File           : main.c                                                 *
*  Project        : YAC (Yet Another CORDIC Core)                          *
*  Creation       : Jun. 2015                                              *
*  Limitations    :                                                        *
*  Platform       : Linux                                                  *
*  Target         : Linux-Os                                               *
*                                                                          *
*  Author(s):     : Christian Haettich                                     *
*  Email          : feddischson@opencores.org                              *
*                                                                          *
*                                                                          *
**                                                                        **
*                                                                          *
*  Description                                                             *
*        C implementation for a test system: PC part.                      *
*        This implementation sends messages via serial line.               *
*        Each message contains a calculation request, and each answer      *
*        contains the calculation result                                   *
*        All messages have the same size, starting with a synchronization  *
*        byte and a header byte.                                           *
*                                                                          *
*                                                                          *
****************************************************************************
*                                                                          *
*                     Copyright Notice                                     *
*                                                                          *
*    This file is part of YAC - Yet Another CORDIC Core                    *
*    Copyright (c) 2015, Author(s), All rights reserved.                   *
*                                                                          *
*    YAC is free software; you can redistribute it and/or                  *
*    modify it under the terms of the GNU Lesser General Public            *
*    License as published by the Free Software Foundation; either          *
*    version 3.0 of the License, or (at your option) any later version.    *
*                                                                          *
*    YAC 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     *
*    Lesser General Public License for more details.                       *
*                                                                          *
*    You should have received a copy of the GNU Lesser General Public      *
*    License along with this library. If not, download it from             *
*    http://www.gnu.org/licenses/lgpl                                      *
*                                                                          *
***************************************************************************/
 
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <endian.h>
#include <math.h>
 
#include "msg.h"
#include "yac.h"
#include "crc.h"
 
 
/**
 * Some error numbers used by this little tool
 */
#define ERR_NONE      0   /* no error               */
#define ERR_CRC       1   /* CRC error              */
#define ERR_TIMEOUT   2   /* Timeout error          */
#define ERR_CALC      3   /* Calculation error      */
#define ERR_SYNC      4   /* Synchronization error  */
#define ERR_SERIAL    5   /* Serial comm. error     */
 
#if 0
 #define VERBOSE 
#endif
 
 
/* 
 * implemented in cordic_iterative.c 
 */
extern
void cordic_int( long long int   x_i, 
                 long long int   y_i,
                 long long int   a_i,
                 long long int * x_o,
                 long long int * y_o,
                 long long int * a_o,
                 int           * it_o,
                 int        mode,
                 int        XY_WIDTH,
                 int        A_WIDTH,
                 int        GUARD_BITS,
                 int        RM_GAIN );
 
 
/*
 * global message buffers
 */
static Msg global_out_buf;
static Msg global_in_buf;
 
 
/*
 * local functions
 */
uint8_t do_test           ( int fd, int x, int y, int z, int mode );
uint8_t do_sync           ( int fd );
uint8_t run_random_test   ( int fd, uint32_t n_test );
int     init_serial_port  ( char* portname, int baud, int timeout );
void    print_usage_and_exit( void );
 
 
 
 
int main( int argc, char* argv[] )
{
  int       i;
  char*     portname ;
  int       baud;
  int       serial_fd;
  int       n_tests;
 
  if( argc != 4 )
    print_usage_and_exit( );
 
  if( 1 != sscanf( argv[3], "%d", &n_tests ) )
    print_usage_and_exit( );
  if( 1 != sscanf( argv[2], "%d", &baud ) )
    print_usage_and_exit( );
  portname = argv[1];
 
 
 
  memset( global_out_buf.bytes, 0, sizeof( Msg ) );
  global_out_buf.fields.sync = SYNC_BYTE;
 
 
  serial_fd = init_serial_port( portname, baud, 10 );
  if( -1 == serial_fd )
    return -1;
 
  if( ERR_NONE != do_sync( serial_fd ) )
    fprintf( stderr, "Error: failed to sync\n" );
 
  run_random_test( serial_fd, n_tests );
 
  return 0;
}
 
/* 
 * Prints some usage message
 */
void print_usage_and_exit( void )
{
  printf( "Usage: TODO <port> <baud> <n-tests>\n" );
  exit( -1 );
}
 
 
 
/**
 * Initializes the serial port
 */
int init_serial_port( char* portname, int baud, int timeout )
{
 
  struct termios tty;
  int serial_fd = open ( portname, O_RDWR | O_NOCTTY | O_SYNC );
  if( serial_fd == -1 )
  {
    fprintf( stderr, "Error: Failed to open serial port %s\n", portname );
    return -1;
  }
 
  memset (&tty, 0, sizeof( tty ) );
  if (tcgetattr ( serial_fd, &tty ) != 0)
  {
    fprintf( stderr, "Error %d from tcgetattr", errno );
    return -1;
  }
 
  cfsetospeed (&tty, baud);
  cfsetispeed (&tty, baud);
 
  tty.c_cflag     = (tty.c_cflag & ~CSIZE) | CS8;
  tty.c_iflag    &= ~IGNBRK;         
  tty.c_lflag     = 0;                
 
  tty.c_oflag     = 0;                
  tty.c_cc[VMIN]  = 0;                       /* non blocking */
  tty.c_cc[VTIME] = 1;      
 
  tty.c_iflag    &= ~(IXON | IXOFF | IXANY); /* shut off xon/xoff ctrl */
  tty.c_cflag    |= (CLOCAL | CREAD);
  tty.c_cflag    &= ~(PARENB | PARODD);
  tty.c_cflag    |= 0;                       /* parity */
  tty.c_cflag    &= ~CSTOPB;
  tty.c_cflag    &= ~CRTSCTS;
 
  if (tcsetattr ( serial_fd, TCSANOW, &tty ) != 0)
  {
    fprintf( stderr, "Error %d from tcsetattr", errno);
    return -1;
  }
 
  return serial_fd;
}
 
 
/**
 * Function to send and receive one message.
 *
 */
uint8_t snd_rcv( int fd, Msg out_buf, Msg * in_buf, int fail_cnt )
{
  int w_bytes, r_bytes;
  uint8_t *ptr;
  uint8_t crc_in;
  out_buf.fields.payload[ 0 ] = htobe32( out_buf.fields.payload[ 0 ] );
  out_buf.fields.payload[ 1 ] = htobe32( out_buf.fields.payload[ 1 ] );
  out_buf.fields.payload[ 2 ] = htobe32( out_buf.fields.payload[ 2 ] );
 
  out_buf.fields.crc = crc( out_buf.bytes, sizeof( Msg )-1 );
 
  w_bytes = write( fd, out_buf.bytes, sizeof( Msg ) );
 
  if( w_bytes != sizeof( Msg ) )
    return ERR_SERIAL;
 
  ptr = &in_buf->bytes[ 0 ];
  while( w_bytes )
  {
    r_bytes = read( fd, ptr, w_bytes );
    ptr     += r_bytes;
    w_bytes -= r_bytes;
 
    if( --fail_cnt == 0 )
    {
      #if 0
      printf( "timeout\n" );
      #endif
      return ERR_TIMEOUT;
    }
  }
  crc_in = crc( in_buf->bytes, sizeof( Msg )-1 );
  in_buf->fields.payload[ 0 ] = be32toh( in_buf->fields.payload[ 0 ] );
  in_buf->fields.payload[ 1 ] = be32toh( in_buf->fields.payload[ 1 ] );
  in_buf->fields.payload[ 2 ] = be32toh( in_buf->fields.payload[ 2 ] );
  if( crc_in != in_buf->fields.crc )
  {
    #if 0
    printf( "crc error (%x <-> %x )\n", crc_in, in_buf->fields.crc ); 
    #endif
    return ERR_CRC;
  }
 
  if( in_buf->fields.sync == out_buf.fields.sync )
    return ERR_NONE;
  else
    return ERR_SYNC;
}
 
/**
 * Send and receive a synchronization message 
 * ( empty NOP message )
 */
uint8_t do_sync( int fd )
{
  uint8_t res;
 
  global_out_buf.fields.header = CMD_NOP;
  res = snd_rcv( fd, global_out_buf, &global_in_buf, 40 );
  if( res != ERR_NONE )
    return res;
 
 
  if( global_in_buf.fields.sync   == global_out_buf.fields.sync &&
      global_in_buf.fields.header == global_out_buf.fields.header )
    return ERR_NONE;
  else
    return ERR_SYNC;
}
 
 
 
 
 
/** 
 * Function to run n_test tests
 *
 */
uint8_t run_random_test( int fd, uint32_t n_test )
{
 
  uint8_t  res;
  uint32_t test_cnt = 0;
  uint32_t calc_cnt = 0;
  uint32_t crc_cnt  = 0;
  uint32_t othr_cnt = 0;
 
  srand( 1234 );
  uint32_t i;
  for( i=0; i < n_test; i++, test_cnt++ )
  {
    int32_t y = ( rand() % ( (int32_t) pow( 2, YAC_XY_WIDTH ) ) ) - pow( 2, YAC_XY_WIDTH-1 );
    int32_t x = ( rand() % ( (int32_t) pow( 2, YAC_XY_WIDTH ) ) ) - pow( 2, YAC_XY_WIDTH-1 );
 
    res = do_test( fd, x, y, 0,  YAC_FLAG_VEC_ROT | YAC_MODE_CIR   );
 
    if( ERR_NONE != res )
    {
      if( res == ERR_CALC )
        calc_cnt++;
      else if( res == ERR_CRC )
        crc_cnt++;
      else
        othr_cnt++;
 
    }
  }
 
  printf(" %d of %d tests failed, (crc-errors: %d, other errors: %d )\n", 
        calc_cnt, 
        test_cnt,
        crc_cnt,
        othr_cnt );
 
  return ERR_NONE;
}
 
 
/**
 * Run one single test
 *
 */
uint8_t do_test( int fd, int x, int y, int z, int mode )
{
  long long int xo;
  long long int yo;
  long long int zo;
  uint8_t res;
  int it;
 
  /* local calculation */
  cordic_int(
    x, y, z, &xo, &yo, &zo, &it, mode, 
      YAC_XY_WIDTH, 
      YAC_A_WIDTH,
      2,
      YAC_RM_GAIN
      );
 
 
  /* remote calculation */
  global_out_buf.fields.header = CMD_CALC;
  global_out_buf.fields.payload[ 0 ] = x;
  global_out_buf.fields.payload[ 1 ] = y;
  global_out_buf.fields.payload[ 2 ] = z;
  global_out_buf.fields.mode         = mode;
  res = snd_rcv( fd, global_out_buf, &global_in_buf, 10 );
  if( ERR_NONE != res  )
    return res;
 
  # if defined (VERBOSE)
  printf("( %d <-> %d ) \n", global_in_buf.fields.payload[0], (int)xo );
  printf("( %d <-> %d ) \n", global_in_buf.fields.payload[1], (int)yo );
  printf("( %d <-> %d ) \n", global_in_buf.fields.payload[2], (int)zo );
  #endif
 
  /* result comparions */
  if ( (xo == global_in_buf.fields.payload[0]) && 
       (yo == global_in_buf.fields.payload[1]) && 
       (zo == global_in_buf.fields.payload[2])  ) 
    return ERR_NONE;
  else
    return ERR_CALC;
 
}
 
 
 

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.