-- Model Name : Concurrent - Concurrent Package -- Author : Armita Peymandoust -- Last Updated : 09 / 15 / 1996 -- This document is © copyrighted by the Author.

USE WORK.synthesis_utilities.ALL;
USE WORK.synthesis_parameters.ALL;
USE WORK.global_environment.ALL;

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;

LIBRARY STD;
USE STD.textio.ALL;

-------------------------------------------------------------------------

PACKAGE PackCon IS

  PROCEDURE DeAlloc (input : INOUT byte_node_ptr);
  PROCEDURE Equate (VARIABLE source : IN byte_node_ptr; dest : INOUT byte_node_ptr);

  PROCEDURE DeAlloc (input : INOUT nibble_node_ptr);
  PROCEDURE Equate (VARIABLE source : IN nibble_node_ptr; dest : INOUT nibble_node_ptr);
    

  PROCEDURE AddSub (AddOrSub: IN std_logic; VARIABLE i1, i2: IN byte_node_ptr; o: OUT by
te_node_ptr; VARIABLE flagsin: IN nibble_node_ptr; flags : OUT nibble_node_ptr);
  PROCEDURE AndSetFlags(VARIABLE i1, i2 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIA
BLE flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr);     
  PROCEDURE EquateSetFlags(VARIABLE i1 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIAB
LE flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr);
  PROCEDURE NotSetFlags(VARIABLE i1 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIABLE 
flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr);
  
  PROCEDURE ShiftLeft(i : INOUT byte_node_ptr; i2 : INOUT nibble_node_ptr);
  PROCEDURE ShiftRight(i : INOUT byte_node_ptr; i2 : INOUT nibble_node_ptr);
      
END PackCon;

--------------------------------------------------------------------------

PACKAGE BODY PackCon IS

--**********************************************************************

  PROCEDURE DeAlloc (input : INOUT byte_node_ptr) IS
    VARIABLE temp : byte_node_ptr;
  BEGIN
    WHILE (input/=NULL AND input/=zero_8) LOOP
      temp := input;
      input := input.link;
      DEALLOCATE (temp);
    END LOOP;         
  END DeAlloc;   
  
  PROCEDURE Equate (VARIABLE source : IN byte_node_ptr; dest : INOUT byte_node_ptr) IS
    VARIABLE temp, temp2 : byte_node_ptr := NULL;
  BEGIN  
    dest := NEW byte_node;
    dest.val := source.val;
    temp := source.link; 
    temp2 := dest;
    WHILE temp/=NULL LOOP
      temp2.link := NEW byte_node;
      temp2 := temp2.link;
      temp2.val := temp.val;
      temp := temp.link;
    END LOOP;
  END Equate;
--************************************************************************
  PROCEDURE DeAlloc (input : INOUT nibble_node_ptr) IS
    VARIABLE temp : nibble_node_ptr;
  BEGIN
    WHILE (input/=NULL AND input/=zero_4) LOOP
      temp := input;
      input := input.link;
      DEALLOCATE (temp);
    END LOOP;         
  END DeAlloc;   
  
  PROCEDURE Equate (VARIABLE source : IN nibble_node_ptr; dest : INOUT nibble_node_ptr) 
IS
    VARIABLE temp, temp2 : nibble_node_ptr := NULL;
  BEGIN  
    dest := NEW nibble_node;
    dest.val := source.val;
    temp := source.link; 
    temp2 := dest;
    WHILE temp/=NULL LOOP
      temp2.link := NEW nibble_node;
      temp2 := temp2.link;
      temp2.val := temp.val;
      temp := temp.link;
    END LOOP;
  END Equate;                      

--*******************************************************************
  PROCEDURE AddSub (AddOrSub: IN std_logic; VARIABLE i1, i2: IN byte_node_ptr; o: OUT by
te_node_ptr; VARIABLE flagsin: IN nibble_node_ptr; flags : OUT nibble_node_ptr) IS
    VARIABLE temp : std_logic_vector (9 DOWNTO 0);
    VARIABLE a, b, t : byte_node_ptr;
    VARIABLE sr_t, tf : nibble_node_ptr;
  BEGIN      
     a := i1;
     b := i2;
     sr_t := flagsin;
     t := NEW byte_node;
     o := t;
     tf := NEW nibble_node;
     flags := tf;
     LOOP
       temp := addsub_cv (a.val, b.val, sr_t.val(2), AddOrSub);
       t.val := temp(7 DOWNTO 0);
          
       tf.val(2) := temp(8);  --c
       tf.val(3) := temp(9);  --v
       tf.val(0) := temp(7);  --n
       tf.val(1) := NOT all_or (t.val(7 DOWNTO 0));  --z
       IF (a.link=NULL AND b.link=NULL) THEN EXIT; END IF;
       IF (a.link/=NULL) THEN a:=a.link; END IF; 
       IF (b.link/=NULL) THEN b:=b.link; END IF;
       IF (sr_t.link/=NULL) THEN sr_t:=sr_t.link; END IF;
       t.link := NEW byte_node;
       tf.link := NEW nibble_node;
       tf := tf.link;
       t:=t.link;    
     END LOOP;
  END AddSub;
--********************************************************************************
  PROCEDURE AndSetflags(VARIABLE i1, i2 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIA
BLE flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr) IS
    VARIABLE a, b, t : byte_node_ptr;
    VARIABLE sr_t, tf : nibble_node_ptr;
  BEGIN            
    a := i1;
    b := i2;                
    sr_t := flagsin;
    t := NEW byte_node;
    o:=t;
    tf := NEW nibble_node;
    flags := tf;
    LOOP
      t.val := a.val AND b.val;
      tf.val(2) := sr_t.val(2);  --c
      tf.val(3) := sr_t.val(3);  --v
      tf.val(0) := t.val(7);  --n
      tf.val(1) := NOT all_or (t.val(7 DOWNTO 0));  --n

      IF (a.link=NULL AND b.link=NULL) THEN EXIT; END IF;
      IF (a.link/=NULL) THEN a:=a.link; END IF; 
      IF (b.link/=NULL) THEN b:=b.link; END IF;
      IF (sr_t.link/=NULL) THEN sr_t:=sr_t.link; END IF;
      t.link := NEW byte_node;
      tf.link := NEW nibble_node;
      tf := tf.link;
      t:=t.link;    
    END LOOP;
  END AndSetFlags;

--*****************************************************************************
  PROCEDURE EquateSetFlags(VARIABLE i1 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIAB
LE flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr) IS
    VARIABLE a, t : byte_node_ptr;
    VARIABLE sr_t, tf : nibble_node_ptr;
  BEGIN           
    a := i1;
    sr_t := flagsin;
    t := NEW byte_node;
    o := t;
    tf := NEW nibble_node;
    flags := tf;
    LOOP
      t.val := a.val;
      tf.val(2) := sr_t.val(2);  --c
      tf.val(3) := sr_t.val(3);  --v
      tf.val(0) := t.val(7);  --n
      tf.val(1) := NOT all_or (t.val(7 DOWNTO 0));  --n
      IF a.link=NULL THEN EXIT; END IF;
      a:=a.link;
      IF (sr_t.link/=NULL) THEN sr_t:=sr_t.link; END IF;
      t.link := NEW byte_node;
      tf.link := NEW nibble_node;
      tf := tf.link;
      t:=t.link;    
    END LOOP;
  END EquateSetFlags;           
  
--***********************************************************************
  PROCEDURE NotSetFlags(VARIABLE i1 : IN byte_node_ptr; o : OUT byte_node_ptr; VARIABLE 
flagsin : IN nibble_node_ptr; flags: OUT nibble_node_ptr) IS
    VARIABLE a, t : byte_node_ptr;
    VARIABLE sr_t, tf : nibble_node_ptr;
  BEGIN
    a := i1;
    sr_t := flagsin;
    t := NEW byte_node;
    o := t;
    tf := NEW nibble_node;
    flags := tf;
    LOOP
      t.val := NOT a.val;
      tf.val(2) := sr_t.val(2);  --c
      tf.val(3) := sr_t.val(3);  --v
      tf.val(0) := t.val(7);  --n
      tf.val(1) := NOT all_or (t.val(7 DOWNTO 0));  --n
      IF a.link=NULL THEN EXIT; END IF;
      a:=a.link;
      IF (sr_t.link/=NULL) THEN sr_t:=sr_t.link; END IF;
      t.link := NEW byte_node;
      tf.link := NEW nibble_node;
      tf := tf.link;
      t:=t.link;    
    END LOOP;
  END NotSetFlags;  
--**********************************************************************
  PROCEDURE ShiftLeft(i : INOUT byte_node_ptr; i2 : INOUT nibble_node_ptr) IS
    VARIABLE t : byte_node_ptr; 
    VARIABLE t2 : nibble_node_ptr;
  BEGIN
    t := i;
    t2 := i2;      
    WHILE t/=NULL LOOP
      t2.val(2) := t.val (7);
      t2.val(3) := t.val (6) XOR t.val (7);
      t.val := t.val (6 DOWNTO 0) & '0';
      t2.val(0) := t.val (7);
      t2.val(1) := NOT all_or (t.val);
      t:=t.link;
      t2:=t2.link;
    END LOOP;
  END ShiftLeft;
  
  PROCEDURE ShiftRight(i : INOUT byte_node_ptr; i2 : INOUT nibble_node_ptr) IS
    VARIABLE t : byte_node_ptr; 
    VARIABLE t2 : nibble_node_ptr;
  BEGIN                                          
    t := i;
    t2 := i2;
    WHILE t/=NULL LOOP
      t.val := t.val (6 DOWNTO 0) & '0';
      t2.val(0) := t.val (7);
      t2.val(1) := NOT all_or (t.val);
      t:=t.link;
      t2:=t2.link;
    END LOOP;
  END ShiftRight;  

END PackCon;