cv.c 6.91 KB
/**************************************************************************
 *                                                                        *
 *               Copyright (C) 1994, Silicon Graphics, Inc.               *
 *                                                                        *
 *  These coded instructions, statements, and computer programs  contain  *
 *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
 *  are protected by Federal copyright law.  They  may  not be disclosed  *
 *  to  third  parties  or copied or duplicated in any form, in whole or  *
 *  in part, without the prior written consent of Silicon Graphics, Inc.  *
 *                                                                        *
 **************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#include "cv.h"

/*
 *  Coverage Unit
 *
 *  8/30 RJM
 *  $Id: cv.c,v 1.1.1.1 2002/05/02 03:28:45 blythe Exp $
 */

#define POSEDGE         (save_clk && !save_clk_old)
#define NEGEDGE         (!save_clk && save_clk_old)

#ifndef MAX
#define MAX(x, y)       (((x) > (y)) ? (x) : (y))
#endif

#ifndef MIN
#define MIN(x, y)       (((x) < (y)) ? (x) : (y))
#endif

/*
 *  Generate left boundary mask
 */
static unsigned int
  get_left_row_mask(int curx, int xm)
{
  unsigned int sticky;
  unsigned int xfrac;
  unsigned int lr;
  unsigned int x;

  x = (xm >> 3) & 0xfff;
  sticky = xm & 1;
  xfrac = (xm >> 1) & 3;

  if((curx & 0x800) || ((x & 0x3ff) > (curx & 0x3ff)))
    lr = 0x0;
  else if(curx & 0x400 || ((x & 0x3ff) < (curx & 0x3ff)))
    lr = 0xf;
  else /* equal */
    lr = 0xf >> (xfrac + sticky);

  return(lr);
}

/*
 *  Generate right boundary mask
 */
static unsigned int
  get_right_row_mask(int curx, int xm)
{
  unsigned int sticky;
  unsigned int xfrac;
  unsigned int rr;
  unsigned int x;

  x = (xm >> 3) & 0xfff;
  sticky = xm & 1;
  xfrac = (xm >> 1) & 3;

  if((curx & 0x800) || ((curx & 0x3ff) > (x & 0x3ff)))
    rr = 0x0;
  else if(curx & 0x400 || ((curx & 0x3ff) < (x & 0x3ff)))
    rr = 0xf;
  else /* equal */
    rr = 0xf0 >> (xfrac + sticky);

  return(rr & 0xf);
}





/*====================================================================
  = cv(): main interface routine for coverage unit
  =
  ====================================================================
*/
void
  cv(cv_t **pp0, cv_t **pp1)
{
  /* pointers to memory structure */
  cv_t *p0, *p1;
  int i;
  int save_clk;
  int save_clk_old;
 
  unsigned int ew_cv_data;
 
  /* intermediate values */
  int add_val;
 
  unsigned int lmask = 0;
  unsigned int rmask = 0;
  unsigned int mask;
  unsigned int cvg;

  unsigned int y_mask;
  unsigned int x_mask;
  unsigned int y_offset;
  unsigned int x_offset;

  /*
   *  Get pointers, clocks
   */
  p0 = *pp0;
  p1 = *pp1;
  save_clk = p0->gclk;
  save_clk_old = p1->gclk_old;

  if(NEGEDGE)
  {
    ew_cv_data = p0->ew_cv_data;
  }
  else
    ew_cv_data = 0;

  if(POSEDGE)
  {
    /* transfer all next-clock register values to register outputs. */
    *pp0 = p1; /* swap */
    *pp1 = p0;
    p0 = *pp0; /* fix pointers */
    p1 = *pp1;
  }

  if(POSEDGE || NEGEDGE)
  {
    /* Update all next-clock register values */
    
    /* pipeline between Edge Walker and Coverage */
    p0->xm3 = ew_cv_data;
    p0->xh3 = p1->xm3;
    p0->xm2 = p1->xh3;
    p0->xh2 = p1->xm2;
    p0->xm1 = p1->xh2;
    p0->xh1 = p1->xm1;
    p0->xm0 = p1->xh1;
    p0->xh0 = p1->xm0;

    /* 
     *  select xmax/xmin 
     */
    p0->xmin3 = p1->ew_cv_newspan ? (p1->left ? p1->xh3 : p1->xm3) : p1->xmin3;
    p0->xmax3 = p1->ew_cv_newspan ? (p1->left ? p1->xm3 : p1->xh3) : p1->xmax3;
    p0->xmin2 = p1->ew_cv_newspan ? (p1->left ? p1->xh2 : p1->xm2) : p1->xmin2;
    p0->xmax2 = p1->ew_cv_newspan ? (p1->left ? p1->xm2 : p1->xh2) : p1->xmax2;
    p0->xmin1 = p1->ew_cv_newspan ? (p1->left ? p1->xh1 : p1->xm1) : p1->xmin1;
    p0->xmax1 = p1->ew_cv_newspan ? (p1->left ? p1->xm1 : p1->xh1) : p1->xmax1;
    p0->xmin0 = p1->ew_cv_newspan ? (p1->left ? p1->xh0 : p1->xm0) : p1->xmin0;
    p0->xmax0 = p1->ew_cv_newspan ? (p1->left ? p1->xm0 : p1->xh0) : p1->xmax0;

    p0->xval = p1->ew_cv_newspan ? ew_cv_data & 0xf : p1->xval;

    if(p1->reset_l == 0)
    {
      p0->x_cur = 0;
      p0->comp_new = 0;
    }
    else
    {
      p0->comp_new = p1->ew_cv_newspan ? (~p1->cycle_type) & 1 : 
	(p1->cycle_type ? (~p1->comp_new) & 1 : p1->comp_new);
      if(p1->left )
	add_val = p1->comp_new & 1;
      else
	add_val = p1->comp_new ? 0xfff : 0;
      p0->x_cur = p1->ew_cv_newspan ? p1->ew_cv_start_x : (p1->x_cur + add_val);
    }

    /*
     *  Find mask
     */
  
    lmask  = get_left_row_mask(p1->x_cur, p1->xmin0) << 12;
    lmask |= get_left_row_mask(p1->x_cur, p1->xmin1) << 8;
    lmask |= get_left_row_mask(p1->x_cur, p1->xmin2) << 4;
    lmask |= get_left_row_mask(p1->x_cur, p1->xmin3);

    rmask  = get_right_row_mask(p1->x_cur, p1->xmax0) << 12;
    rmask |= get_right_row_mask(p1->x_cur, p1->xmax1) << 8;
    rmask |= get_right_row_mask(p1->x_cur, p1->xmax2) << 4;
    rmask |= get_right_row_mask(p1->x_cur, p1->xmax3);

    p0->mask_l = lmask;
    p0->mask_r = rmask;

    mask = lmask & rmask & 0xa5a5;
    mask &= (p1->xval & 8) ? 0xffff : 0x0fff;
    mask &= (p1->xval & 4) ? 0xffff : 0xf0ff;
    mask &= (p1->xval & 2) ? 0xffff : 0xff0f;
    mask &= (p1->xval & 1) ? 0xffff : 0xfff0;
   
    /*
     *  Find coverage value
     */

    p0->mask15 = (mask >> 15) & 1;
    for(cvg = i = 0; i < 16; i++)
       cvg += (mask >> i) & 1;

    p0->cv_value = cvg;


    /*
     *  get x/y subpixel offsets
     */
    y_mask  = (mask & 0xf000) > 0;
    y_mask |= ((mask & 0x0f00) > 0) << 1;
    y_mask |= ((mask & 0x00f0) > 0) << 2;
    y_mask |= ((mask & 0x000f) > 0) << 3;

    y_offset = (((y_mask & 2) && !(y_mask & 1)) || 
		((y_mask & 8) && !(y_mask & 4) && !(y_mask & 1))) & 1;
    y_offset |= ((((y_mask & 4) || (y_mask & 8)) && 
		!(y_mask & 2) && !(y_mask & 1)) << 1) & 2;

    switch(y_offset)
    {
      case 0:
    	x_mask = (mask & 0xf000) >> 12;
	break;
      case 1:
    	x_mask = (mask & 0x0f00) >> 8;
	break;
      case 2:
    	x_mask = (mask & 0x00f0) >> 4;
	break;
      case 3:
    	x_mask = (mask & 0x000f);
  	break;
    }

    x_offset = (((x_mask & 4) && !(x_mask & 8)) || 
		((x_mask & 1) && !(x_mask & 2) && !(x_mask & 8))) & 1;
    x_offset |= ((((x_mask & 2) || (x_mask & 1)) && 
		!(x_mask & 4) && !(x_mask & 8)) << 1) & 2;

    p0->y_offset = y_offset & 3;
    p0->x_offset = x_offset & 3;

    /* dither, same clock as x_cur */
    p0->x_dither = p0->x_cur & 3;


    /* DEBUG */
    p0->mask = mask;

  } /* exec module */

  /* save last clock state */
   p0->gclk_old = p1->gclk_old = save_clk;

}



/*====================================================================
  = cv_init(): initialization routine for coverage unit
  =
  ====================================================================
*/
void
  cv_init(cv_t *p0, cv_t *p1)
{
    p1->gclk = p0->gclk = 0;
    p1->gclk_old = p0->gclk_old = 0;
}