/*
 *
 * Copyright © 1996 Norlinvest Ltd. All rights reserved.
 * EDComX, EDSpice, EDWin, EE Designer, CompCAD, CAD 1000,
 * CAD ABC and Visionics are trade marks of Norlinvest Ltd.
 * Copyright © 1983 - 2002.
 *
 */

#include "LPrim.h"

// Some help full subroutins

WORD And(register WORD x, register WORD y)
{
   x &= LSTATE;
   y &= LSTATE;
   return (x < y)? x: y;
}

WORD Or(register WORD x, register WORD y)
{
   x &= LSTATE;
   y &= LSTATE;
   return (x > y)? x: y;
}

WORD Xor(register WORD x, register WORD y)
{
   x &= LSTATE;
   if (x == XSTAT1 || x == XSTAT2) return XSTAT1;
   y &= LSTATE;
   if (y == XSTAT1 || y == XSTAT2) return XSTAT1;
   return x ^ y;
}

WORD Not(register WORD x)
{
   x ^= LSTATE;
   return(x & LSTATE);
}

#define ea 0xffff   // End of argument

// Calculate And for n args of 0xffff terminated list

WORD Andn(WORD n, ...)
{
   WORD result = n;
   WORD arg;

   va_list ap;
   va_start(ap, n);

   while((arg = va_arg(ap, WORD)) != ea)
   {
      result = And(result, arg);
   }
   va_end(ap);
   return result;
}

// Calculate Or for n args

WORD Orn(WORD n, ...)
{
   WORD result = n;
   WORD arg;

   va_list ap;
   va_start(ap, n);

   while((arg = va_arg(ap, WORD)) != ea)
   {
      result = Or(result, arg);
   }
   va_end(ap);
   return result;
}

unsigned long LSTAT_TO_NORM(long a, int n)
{
   int i;
   long b, z;

   // Check only least or most significant bit in 2-bit logic state

   // 1st bit
   for(i = 0, z = 1, b = 0; i < n ; i++, z <<= 2) b |= (a & z) >> (i);
   return b;

   // 2nd bit
   for(i = 0, z = 2, b = 0; i < n ; i++, z <<= 2) b |= (a & z) >> (i + 1);
   return b;
}

unsigned long NORM_TO_LSTAT(long a, int n)
{
   DWORD b;
   int i;

   for(i = 0, b = 0; i < n; i++) b |= ((a & (1 << i)) * 3) << i;
   return b;
}

unsigned long CONV_LS_N(long a)
{
   return (LSTAT_TO_NORM(a, 8));
}

unsigned long CONV_N_LS(long a)
{
   return (NORM_TO_LSTAT(a, 8));
}

// Check logic state for 1 LSbit
// return 1 if a - correct LS, 0 for bad state

unsigned long CHECK_LS(WORD a)
{
   a &= LSTATE;
   
   return((a != LOW && a != HIGH ) ? 0 : 1);
}

// Check logic state for max 8 LS bits 

unsigned long CHECK_LS_WORD(WORD a, int n)
{
   register int k, i;
   
   n = (n > 8) ? 8 : n;

   for(i = 0; i < n; i++, a >>= 2)
   {
      k = a & LSTATE;
      
      if(k != LOW && k != HIGH) return 0;
   }
   return 1;
}

// Check logic state for max 16 LS bits

unsigned long CHECK_LS_DWORD(long a, int n)
{
   register long k, i;
   
   n = (n > 16) ? 16 : n;

   for(i = 0; i < n; i++, a >>= 2)
   {
      k = a & LSTATE;
      
      if(k != LOW && k != HIGH) return (unsigned long) 0;
   }
	return 1;
}                                   

// Make bad LS state for a ( a can be bad LS)

long MK_BAD_LS(WORD a)
{
   return(XSTAT1);
}

// same for LS WORD 

long MK_BAD_LS_WORD(WORD a, int n)
{
   register int i;
   WORD         b = 0;
   
   n = (n > 16) ? 16 : n;

   for(i = 0; i < n; i++) b |= (MK_BAD_LS(a >> (i * 2)) << (i * 2));
   return(b);
}

// Messages

void M_SIMTIME_ERR(void)
{
   MESSAGE("SimTime less than last change time!!!");
}

void M_BAD_LS(char *s)
{
   char b[80];
   sprintf(b, "%s have bad logic state !!", s); MESSAGE(b);
}

void M_PERIOD_SHORT(char *s)
{
   char b[80];
   sprintf(b, "%s period is too short", s); MESSAGE(b);
}

void M_PULSE_SHORT(char *s)
{
   char b[80];
   sprintf(b, "%s pulse is too short", s); MESSAGE(b);
}

void M_RECVRY_ERR(char *s, char*p)
{
   char b[80];
   sprintf(b, "%s was change during recovery time to %s ", s, p); MESSAGE(b);
}

void M_SETUP_ERR(char *s, char*p)
{
   char b[80];
   sprintf(b, "%s was change during %s setup time", s, p); MESSAGE(b);
}

void M_BADLS_LOAD(char *s)
{
   char b[80];
   sprintf(b, "%s have bad logic state during loading", s); MESSAGE(b);
}

void M_BADLS_SETUP(char *s, char *p)
{
   char b[80];
   sprintf(b, "%s have bad logic state during setup to %s", s, p); MESSAGE(b);
}

void M_HOLD_ERR(char *s, char*p)
{
   char b[80];
   sprintf(b, "%s changed during %s hold time", s, p); MESSAGE(b);
}
