/**************************************************************************
 *                                                                        *
 *               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 "ep.h"

/*
 *  Edge Walker Pipe Unit
 *
 *  This module delays edge walker calulated attribute start points
 *  for the span until needed by various modules in the pipeline.
 *
 *
 *  9/1/94 RJM
 *  9/30/94 RJM		Reduced width of pipe from 32 to 22 bits.
 *  $Id: ep.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)





/*====================================================================
  = ep(): main interface routine for edge walker pipe unit
  =
  ====================================================================
*/
void
  ep(ep_t **pp0, ep_t **pp1)
{
  /* pointers to memory structure */
  ep_t *p0, *p1;
  int i;
  int save_clk;
  int save_clk_old;
  int two_cycle;

  /* dither stuff */
  int y_dither0, y_dither1, x_dither0, x_dither1;
  int pre_dither0, pre_dither1, pre_dither2;
  

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


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

    /* do dither calculation */
    y_dither0   =  p1->y_dither & 1;
    y_dither1   = (p1->y_dither >> 1) & 1;
    x_dither0   =  p1->x_dither & 1;
    x_dither1   = (p1->x_dither >> 1) & 1;
    pre_dither0 = x_dither1 ^ y_dither1;
    pre_dither1 = (y_dither1 && !p1->dither_type) ^ x_dither0;
    pre_dither2 = x_dither0 ^ y_dither0;
 
    /* delay tc load */
    p0->tc_load_1d = p1->tc_load;

    /* Update all next-clock register values */
    p0->st_span[0] = p1->ew_st_span;
    for(i = 1; i < EP_ST_SPAN_DLY; i++)
      p0->st_span[i] = p1->st_span[i-1];

   
    p0->d[0] = p1->ew_d;
    for(i = 1; i < EP_DATA_DLY; i++)
      p0->d[i] = p1->d[i-1];

  
    p0->x_offset[0] = p1->cv_x_offset;
    for(i = 1; i < EP_XOFFSET_DLY; i++)
      p0->x_offset[i] = p1->x_offset[i-1];

    p0->y_offset[0] = p1->cv_y_offset;
    for(i = 1; i < EP_YOFFSET_DLY; i++)
      p0->y_offset[i] = p1->y_offset[i-1];


    p0->cvg[0] = p1->cv_cvg;
    for(i = 1; i < EP_CVG_DLY; i++)
      p0->cvg[i] = p1->cvg[i-1];

  
    p0->mask[0] = p1->cv_mask;
    for(i = 1; i < EP_MASK_DLY; i++)
      p0->mask[i] = p1->mask[i-1];

    /*
     *  Assign Outputs, one register delay
     */
  
    two_cycle = p1->cycle_type == 1;
 
    p0->st_span_st_w = p1->tlut_en ? 
		p1->st_span[EP_ST_SPAN_W_DLY-1] : 
		p1->st_span[EP_ST_SPAN_W_DLY+1];
    p0->st_span_st_s = (p1->tlut_en && !p1->tc_load_1d) ? 
		p1->st_span[EP_ST_SPAN_S_DLY-1] : 
		p1->st_span[EP_ST_SPAN_S_DLY+1];
    p0->st_span_st_t = (p1->tlut_en  && !p1->tc_load_1d) ? 
		p1->st_span[EP_ST_SPAN_T_DLY-1] : 
		p1->st_span[EP_ST_SPAN_T_DLY+1];
    p0->st_span_st_r = p1->st_span[EP_ST_SPAN_R_DLY-1];
    p0->st_span_st_g = p1->st_span[EP_ST_SPAN_G_DLY-1];
    p0->st_span_st_b = p1->st_span[EP_ST_SPAN_B_DLY-1];
    p0->st_span_st_a = p1->st_span[EP_ST_SPAN_A_DLY-1];
    p0->st_span_st_z = two_cycle ? 
		p1->st_span[EP_ST_SPAN_Z_DLY-1] : 
		p1->st_span[EP_ST_SPAN_Z_DLY-2];
    p0->st_span_tc = (p1->tlut_en && !p1->tc_load_1d) ? 
		p1->st_span[EP_ST_SPAN_TC_DLY-1] : 
		p1->st_span[EP_ST_SPAN_TC_DLY+1];
    p0->st_span_tf = p1->st_span[EP_ST_SPAN_TF_DLY-1];
    p0->st_span_cc = p1->st_span[EP_ST_SPAN_CC_DLY-1];
    p0->st_span_bl = two_cycle ? 
		p1->st_span[EP_ST_SPAN_BL_DLY-1] : 
		p1->st_span[EP_ST_SPAN_BL_DLY-2];
    p0->st_span_ms = two_cycle ? 
		p1->st_span[EP_ST_SPAN_MS_DLY-1] : 
		p1->st_span[EP_ST_SPAN_MS_DLY-3];

    p0->d_w = p1->tlut_en ? p1->ew_d : p1->d[EP_DATA_W_DLY-1];
    p0->d_s = (p1->tlut_en && !p1->tc_load_1d) ? 
		p1->ew_d : 
		p1->d[EP_DATA_S_DLY-1];
    p0->d_t = (p1->tlut_en && !p1->tc_load_1d) ? 
		p1->ew_d : 
		p1->d[EP_DATA_T_DLY-1];
    p0->d_r = p1->d[EP_DATA_R_DLY-1];
    p0->d_g = p1->d[EP_DATA_G_DLY-1];
    p0->d_b = p1->d[EP_DATA_B_DLY-1];
    p0->d_a = p1->d[EP_DATA_A_DLY-1];
    p0->d_z = two_cycle ? 
		p1->d[EP_DATA_Z_DLY-1] : 
		p1->d[EP_DATA_Z_DLY-2];
    p0->x_offset_r = p1->x_offset[EP_XOFFSET_R_DLY-1];
    p0->x_offset_g = p1->x_offset[EP_XOFFSET_G_DLY-1];
    p0->x_offset_b = p1->x_offset[EP_XOFFSET_B_DLY-1];
    p0->x_offset_a = p1->x_offset[EP_XOFFSET_A_DLY-1];
    p0->x_offset_z = two_cycle ? 
		p1->x_offset[EP_XOFFSET_Z_DLY-1] : 
		p1->x_offset[EP_XOFFSET_Z_DLY-2];
    p0->y_offset_r = p1->y_offset[EP_YOFFSET_R_DLY-1];
    p0->y_offset_g = p1->y_offset[EP_YOFFSET_G_DLY-1];
    p0->y_offset_b = p1->y_offset[EP_YOFFSET_B_DLY-1];
    p0->y_offset_a = p1->y_offset[EP_YOFFSET_A_DLY-1];
    p0->y_offset_z = two_cycle ? 
		p1->y_offset[EP_YOFFSET_Z_DLY-1] : 
		p1->y_offset[EP_YOFFSET_Z_DLY-2];
    p0->cvg_cc  = p1->cvg[EP_CVG_CC_DLY-1];
    p0->mask_bl = two_cycle ? 
		p1->mask[EP_MASK_BL_DLY-1] : 
		p1->mask[EP_MASK_BL_DLY-2];

  } /* exec module */

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

}



/*====================================================================
  = ep_init(): initialization routine for edge walker pipe unit
  =
  ====================================================================
*/
void
  ep_init(ep_t *p0, ep_t *p1)
{
    p1->gclk = p0->gclk = 0;
    p1->gclk_old = p0->gclk_old = 0;
}