-- TITLE:
-----------------------------------------------------------------
-- test code for the assembler                         --
-----------------------------------------------------------------
-- Description: Hopefully good assembler code   --
--              					       --
-----------------------------------------------------------------
-- Course: Computer Architecture Project #2                    --
-----------------------------------------------------------------
-- Date | Begin: 12.30.2001                                    --
--      | End  : 12..2001                                    --
-----------------------------------------------------------------
-- Additional Comments:                                        --
--                                                             --
-----------------------------------------------------------------

-- ACCESSING DESIGN LIBRARIES and PACKAGES:
-------------------------------------------

library ieee,work,STD;
----work is working(design) library (there can be only 1!!)

use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;
use STD.textio.all;
------------------------------------------------------------------------------

--ENTITY DECLARATION and PORT MAP: (Interface of design unit to external env.)
----------------------------------

entity assembler is       -- assembler: name of entity
-- no ports
end assembler;
------------------------------------------------------------------------------

--ARCHITECTURE BODY: (Internal details, function of block)
--------------------

architecture testbench of assembler is 

-- SUBPROGRAM DECLARATIONS:
--###############################################
-------------------------------------------------
--  convert to lowercase    
    function lower_case(c : character) return character
    is
    begin
        if c >= 'A' and c <= 'Z' then
            return character'val(character'pos(c) + 32);
        else return c;
        end if;
    end;
----------------------------------------------------
-- compare two strings ignoring case
    function strcmp(a, b : string) return boolean
    is
        alias a_val : string(1 to a'length) is a;
        alias b_val : string(1 to b'length) is b;
        variable a_char, b_char : character;
    begin
        if a'length /= b'length then
            return false;
        elsif a = b then
            return true;
        end if;
        for i in 1 to a'length loop
            a_char := lower_case(a_val(i));
            b_char := lower_case(b_val(i));
            if a_char /= b_char then
                return false;
            end if;
        end loop;
        return true;
    end;
--------------------------------------------------------    
-- compare two chars ignoring case --I WROTE THE OVERLOADED CHAR METHOD
    function strcmp(a, b : character) return boolean
    is
        variable a_char,b_char : character;
    begin
        a_char := lower_case(a);
        b_char := lower_case(b);
        if a_char = b_char then
          return TRUE;
        else
          return FALSE;
        end if;
    end;
 --------------------------------------------------------

-- skip blank characters in read line    
    procedure Skip_white(variable L : in LINE; pos : inout integer)
    is
    begin
        while pos <= L'high loop
            case L(pos) is
                when ' ' | HT  =>
                    pos := pos + 1;
                when others =>
                    exit;
            end case;
        end loop;
    end;
 --------------------------------------------------------    

-- SKIP comma between Register fields:
    procedure Skip_comma(variable instrLine : in LINE; lineends  :in integer; pos : inout integer)
    is
    begin  
      Skip_white(instrLine, pos); -- skip the first blank characters
      if (instrLine(pos) = ',') then
        pos := pos+1; -- go one after ","
      else
        assert (FALSE)
          report "Invalid instruction -->"& instrLine(instrLine'left to lineends)
          severity FAILURE;
      end if;
    end;
 --------------------------------------------------------        

--Display error line on screen:
    procedure errprnt(variable check: inout line; errstr:in string; linenum:in integer) --return boolean
    is
    begin
      write(check,errstr);
      write(check,linenum);
      writeline(output,check);
--      return TRUE;
    end;
-------------------------------------------------------

-- READ THE SUBWORD SIZE:
    procedure Read_SW(variable mnemonic: in LINE; subop: inout std_logic_vector(7 downto 0); pos: in integer; check: inout line; errstr:in string; linenum:in integer; lineends:in integer)
    is 
    begin
      if strcmp(mnemonic(pos+1),'1') then   -- (1.1.1)
        subop(1 downto 0) := "00";
      elsif strcmp(mnemonic(pos+1),'2') then                   
        subop(1 downto 0) := "01";
      elsif strcmp(mnemonic(pos+1),'4') then                   
        subop(1 downto 0) := "10";
      elsif strcmp(mnemonic(pos+1),'8') then                   
        subop(1 downto 0) := "11";
      else
        errprnt(check, errstr, linenum); -- function to print error message and line no
        assert (FALSE)
          report "Invalid instruction [wrong subword size field for ...] -->"& mnemonic(mnemonic'left to lineends)
          severity FAILURE;
      end if; -- end of (1.1.1)
    end;
-------------------------------------------------------    
          
-- READ PREDICATE REGISTER FIELD:
    procedure Read_PRED(variable mnemonic: in LINE; pos: inout integer; prednum: inout integer; check: inout line; errstr:in string; linenum:in integer; lineends:in integer)
    is
    begin
          Skip_white(mnemonic, pos); -- skip the first blank characters
          if strcmp(mnemonic(pos),'P') then -- Predicate register
            if mnemonic(pos+1) >= '0' and mnemonic(pos+1) <= '7' then -- a valid predicate number
              prednum := character'pos(mnemonic(pos+1)) - character'pos('0');
              pos := pos +2;
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[non numeric Predicate id] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if;
          else
            errprnt(check, errstr, linenum); -- function to print error message and line no
            assert (FALSE)
              report "Invalid instruction[expected Predicate register field] -->"& mnemonic(mnemonic'left to lineends)
              severity FAILURE;
          end if; -- end of Predicate register read
    end;    
-------------------------------------------------------



-- READ REGISTER FIELD:
    procedure Read_Reg(variable mnemonic: in LINE; pos: inout integer; regnum: inout integer; check: inout line; errstr:in string; linenum:in integer; lineends:in integer)
    is
    begin
      Skip_white(mnemonic, pos); -- skip the first blank characters
      if strcmp(mnemonic(pos),'R') then -- Rd register
        if mnemonic(pos+1) >= '0' and mnemonic(pos+1) <= '9' then -- a valid reg number
          regnum := character'pos(mnemonic(pos+1)) - character'pos('0');
          pos := pos +2;
          if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid reg number
            regnum := regnum*10 + character'pos(mnemonic(pos)) - character'pos('0');
            pos := pos+1;
          elsif (mnemonic(pos) /= ' ') and (mnemonic(pos) /= ',') then
            errprnt(check, errstr, linenum); -- function to print error message and line no
            assert (FALSE)
              report "Invalid instruction[non numeric Rd/Rs1 register id(2)] -->"& mnemonic(mnemonic'left to lineends)
              severity FAILURE;
          end if;
        else
          errprnt(check, errstr, linenum); -- function to print error message and line no
          assert (FALSE)
            report "Invalid instruction[non numeric Rd/Rs1 register id(1)] -->"& mnemonic(mnemonic'left to lineends)
            severity FAILURE;
        end if;
      else
        errprnt(check, errstr, linenum); -- function to print error message and line no
        --debug options:
        write(check,mnemonic(pos)); -- PRINTS TO O/P WHAT IT READ INSTEAD OF R
        writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
        --
        assert (FALSE)
          report "Invalid instruction[expected Rd register field] -->"& mnemonic(mnemonic'left to lineends)
          severity FAILURE;
      end if; -- end of Rd register read
    end;    
-------------------------------------------------------

-- READ LAST REGISTER FIELD:
    procedure Read_LAST_Reg(variable mnemonic: in LINE; pos: inout integer; regnum: inout integer; check: inout line; errstr:in string; linenum:in integer; lineends:in integer)
    is 
    begin
      Skip_white(mnemonic, pos); -- skip the first blank characters
      if strcmp(mnemonic(pos),'R') then -- Rs2 register
        if mnemonic(pos+1) >= '0' and mnemonic(pos+1) <= '9' then
          regnum := character'pos(mnemonic(pos+1)) - character'pos('0');
          pos := pos +2;
          IF pos <= lineends THEN -- SHOULD CHECK FOR EXCEEDING mnemonic SIZE FOR LAST REG READ
            if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then
              regnum := regnum*10 + character'pos(mnemonic(pos)) - character'pos('0');
              pos := pos+1;
            elsif (mnemonic(pos) /= ' ') and (mnemonic(pos) /= ',') then
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Nonnumeric RS2 field(2) -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if;
          END IF;
        else
          errprnt(check, errstr, linenum); -- function to print error message and line no                      
          assert (FALSE)
            report "Nonnumeric RS2 field(1) -->"& mnemonic(mnemonic'left to lineends)
            severity FAILURE;
        end if;
      else
        errprnt(check, errstr, linenum); -- function to print error message and line no
        assert (FALSE)
          report "Expected Rs2 field -->"& mnemonic(mnemonic'left to lineends)
          severity FAILURE;
      end if; -- end of last register read
    end;    
-------------------------------------------------------

-- READ IMMEDIATE FIELD: *Immediate is always last in instruction!! (Reads up to 5 digits)
    procedure Read_Imm(variable mnemonic: in LINE; pos: inout integer; immval: inout integer; check: inout line; errstr:in string; linenum:in integer; lineends:in integer)
    is
      variable negative : BOOLEAN := FALSE;
    begin
      Skip_white(mnemonic, pos); -- skip the first blank characters
      if strcmp(mnemonic(pos),'-') then -- Negative
          negative := TRUE;
          pos := pos + 1;
          Skip_white(mnemonic, pos); -- skip the blank characters after -
      end if;
          
      if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid imm number
        immval := character'pos(mnemonic(pos)) - character'pos('0');
        pos := pos +1;
        IF pos <= lineends THEN -- SHOULD CHECK FOR EXCEEDING mnemonic SIZE FOR LAST char read
          if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid reg number
            immval := immval*10 + character'pos(mnemonic(pos)) - character'pos('0');
            pos := pos+1;
              IF pos <= lineends THEN -- SHOULD CHECK FOR EXCEEDING mnemonic SIZE FOR LAST char READ
                if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid reg number
                  immval := immval*10 + character'pos(mnemonic(pos)) - character'pos('0');
                  pos := pos+1;
                  IF pos <= lineends THEN -- SHOULD CHECK FOR EXCEEDING mnemonic SIZE FOR LAST char READ               
                    if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid reg number
                      immval := immval*10 + character'pos(mnemonic(pos)) - character'pos('0');
                      pos := pos+1;
                      IF pos <= lineends THEN -- SHOULD CHECK FOR EXCEEDING mnemonic SIZE FOR LAST char READ                  
                        if mnemonic(pos) >= '0' and mnemonic(pos) <= '9' then -- a valid reg number
                          immval := immval*10 + character'pos(mnemonic(pos)) - character'pos('0');
                          pos := pos+1;
                        elsif (mnemonic(pos) /= ' ') then
                          errprnt(check, errstr, linenum); -- function to print error message and line no
                          assert (FALSE)
                            report "Invalid instruction[non numeric Immediate value(5)] -->"& mnemonic(mnemonic'left to lineends)
                            severity FAILURE;
                        end if;
                      END IF;
                    elsif (mnemonic(pos) /= ' ') then
                      errprnt(check, errstr, linenum); -- function to print error message and line no
                      assert (FALSE)
                        report "Invalid instruction[non numeric Immediate value(4)] -->"& mnemonic(mnemonic'left to lineends)
                        severity FAILURE;
                    end if;
                  END IF;
                elsif (mnemonic(pos) /= ' ') then
                  errprnt(check, errstr, linenum); -- function to print error message and line no
                  assert (FALSE)
                    report "Invalid instruction[non numeric Immediate value(3)] -->"& mnemonic(mnemonic'left to lineends)
                    severity FAILURE;
                end if;
              END IF;
          elsif (mnemonic(pos) /= ' ') then
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[non numeric Immediate value(2)] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
          end if;
        END IF;
      else
        errprnt(check, errstr, linenum); -- function to print error message and line no
        assert (FALSE)
          report "Invalid instruction[non numeric Rd/Rs1 register id(1)] -->"& mnemonic(mnemonic'left to lineends)
          severity FAILURE;
      end if;
      if (negative) then
        immval := -1 * immval; -- negate the result
      end if;    
    end;    
-------------------------------------------------------

-- Object declarations:
----------------------------------------------------------- 

file assembly : text open READ_MODE is "/u/canturk/VHDL/testbenchfiles/testfile.asm";
-- file to contain assembly level instr mnemonics i.e. padd.4 R1,R2,R3

file binaryinst   : text open WRITE_MODE is "/u/canturk/VHDL/testbenchfiles/instr_image.ini";
-- file that contains the binary text for the instructions

-- instructiontype type definition:
type inst_type is (ZERO,ONE,TWO,THREE,FOUR_A,FOUR_B,FOUR_C,FIVE_A,FIVE_B);
    
signal TOPtestgoes : boolean := TRUE; 

--signal instr1      :std_logic_vector(31 downto 0);--:= x"00000000"; -- initialize to get rid of UUU...U
-- for some studip reason doesn't work when it's signal
    
BEGIN -- of ARCHITECTURE

  -- READ assembly file:
  assemble: process  -- read the assembly code and convert it into binary
    variable instr1    : std_logic_vector(31 downto 0);  --binary instruction
    
    variable instrtype : inst_type; -- to keep track of instruction types

    variable mnemonic  : line; -- pointer to assembly line
    variable pos       : integer; -- pointer's value                                   
    variable lineends  : integer; -- checks for line end
    variable predicate : std_logic_vector(2 downto 0);
    variable opcode    : std_logic_vector(5 downto 0);
    variable subop     : std_logic_vector(7 downto 0);
    variable Rd        : std_logic_vector(4 downto 0);   
    variable Rs1       : std_logic_vector(4 downto 0);   
    variable Rs2       : std_logic_vector(4 downto 0);
    variable P1        : std_logic_vector(2 downto 0); -- predicate regs for cmp instr-s
    variable P2        : std_logic_vector(2 downto 0); -- predicate regs for cmp instr-s        
    variable imm23     : std_logic_vector(22 downto 0); -- 23 bit immediate
    variable imm18     : std_logic_vector(17 downto 0); -- 18 bit immediate
    variable tag       : std_logic_vector(3 downto 0); -- 4 bit tag of cmp instr-s
    variable regnum    : integer; -- register number
    variable prednum   : integer; -- predicate register number
    variable immval    : integer; -- immediate value
    variable linenum   : integer:= 0; -- keeps track of code lines

    variable writepoint : line; -- pointer that points to the line
                                --that will be written by writeline

    variable check   : line; -- for debugging via writing to screen
    variable str1    : string(1 to 45) := "<<<<<<<<<<<<<<<<<<< STARTS >>>>>>>>>>>>>>>>>>";
    variable errstr  : string(1 to 24) := "***ERROR***: in line -> ";

    begin -- OF PROCESS
 
      write(check,str1);
      writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
      
      readloop: while not endfile(assembly) loop
        readline(assembly,mnemonic); -- point to the beginning of a line
        -- ! pointer(1) NOT 0 points to the 1st char of the read string line!
        linenum := linenum + 1; -- increment line number
        pos := mnemonic'left; -- position of pointer's first point
        Skip_white(mnemonic, pos); -- skip the first blank characters
        -- func_n in STD_TEXTIO     -- increment pos for that
        lineends := mnemonic'right - pos + 1; 

        --## BIGGEST IF: ##-- 
        IF (lineends >= 2) and not(strcmp(mnemonic(pos), '#')) then -- if not blank line not comment
        -- otherwise it is a blank line! or comment line -> skips comments and blank lines
          
          --PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
          --      READ THE PREDICATE REGISTER
          --PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
          Read_PRED(mnemonic, pos, prednum, check, errstr, linenum, lineends);

          -- skip the ":"
          --------------
          Skip_white(mnemonic, pos); -- skip the first blank characters
          if (mnemonic(pos) = ':') then
            pos := pos+1; -- go one after ":"
          else
            assert (FALSE)
              report "Invalid instruction --> expected : after predicate field"& mnemonic(mnemonic'left to lineends)
              severity FAILURE;
          end if;
          
          predicate := std_logic_vector(to_unsigned(prednum,3));    
          Skip_white(mnemonic, pos); -- skip the blank characters after ":"       
          
          --PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
          --      END OF READ THE PREDICATE REGISTER
          --PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
        
          --=======================================================================================    
          --      READ THE INSTRUCTION TYPE:    
          --=======================================================================================
          -- [1] PADD:
          ------------ 
          if strcmp(mnemonic(pos to pos + 3), "PADD") then  --==>> PADD(1)    
            opcode := "110000";
            pos := pos + 4;   
            if strcmp(mnemonic(pos),'.') then -- read subword size (1.1)
              Read_SW(mnemonic, subop, pos, check, errstr, linenum, lineends); -- ReaD SUBWORD procedure
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction [expected subword size field for PADD]-->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.1)
            pos := pos + 2; -- still good instr. with sw
            if strcmp(mnemonic(pos),'.') then -- unsigned or sat add (1.2)
              if strcmp(mnemonic(pos+1),'u') then -- unsigned
                subop(7 downto 2) := "000001";
              elsif strcmp(mnemonic(pos+1),'s') then -- saturation
                subop(7 downto 2) := "000010";
              else 
                errprnt(check, errstr, linenum); -- function to print error message and line no
                assert (FALSE)
                  report "Invalid instruction [expected u or s for padd] -->"& mnemonic(mnemonic'left to lineends)
                  severity FAILURE;
              end if;
              pos := pos + 2; -- we read a saturation or unsigned add
            elsif strcmp(mnemonic(pos),' ') then -- signed add
              subop(7 downto 2) := "000000";
              -- don't increment the pos
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[padd.sw.??] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.2)
            instrtype := FOUR_A; 

          -----------------------------------------------
          --!!!!! psubdecrement'i bundan once tanimlamak lazim, yoksa conflict olur! en once uzun isimler!!  
                -----------------------------------------------
          -- [2] PSUB:
          ------------ 
          elsif strcmp(mnemonic(pos to pos + 3), "PSUB") then  --==>> PSUB(1)    
            opcode := "110000";
            pos := pos + 4;   -- points to '.'
            if strcmp(mnemonic(pos),'.') then -- read subword size (1.1)
              Read_SW(mnemonic, subop, pos, check, errstr, linenum, lineends); -- ReaD SUBWORD procedure
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction [expected subword size field for PSUB]-->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.1)
            -- still points to '.' before subword
            pos := pos + 2; -- still good instr. with sw | points to one after subword
            if strcmp(mnemonic(pos),'.') then -- unsigned or sat sub (1.2)
              if strcmp(mnemonic(pos+1),'u') then -- unsigned
                subop(7 downto 2) := "000101";
              elsif strcmp(mnemonic(pos+1),'s') then -- saturation
                subop(7 downto 2) := "000110";
              else 
                errprnt(check, errstr, linenum); -- function to print error message and line no
                assert (FALSE)
                  report "Invalid instruction [expected u or s for padd] -->"& mnemonic(mnemonic'left to lineends)
                  severity FAILURE;
              end if;
              pos := pos + 2; -- we read a saturation or unsigned sub | points one after u/s
            elsif strcmp(mnemonic(pos),' ') then -- signed sub
              subop(7 downto 2) := "000100";
              -- don't increment the pos
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[psub.sw.??] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.2)
            instrtype := FOUR_A;
            
          -- [3] JUMP:
          ------------ 
          elsif strcmp(mnemonic(pos to pos + 2), "JMP") then  --==>> JMP(1)    
            pos := pos + 3;   -- points to after jmp
            if strcmp(mnemonic(pos),'.') then -- link, reg or reg.link (1.2)
              if strcmp(mnemonic(pos+1 to pos+4),"link") then -- link
                opcode := "000001";
                pos := pos + 5; -- point to one after
                instrtype := ZERO;
              elsif strcmp(mnemonic(pos+1 to pos+8),"reg.link") then -- reg.link
                opcode := "000011";
                pos := pos + 9;-- point to one after
                instrtype := ONE;
              elsif strcmp(mnemonic(pos+1 to pos+3),"reg") then -- reg
                opcode := "000010";  
                pos := pos + 4;-- point to one after
                instrtype := ONE;
              else 
                errprnt(check, errstr, linenum); -- function to print error message and line no
                assert (FALSE)
                  report "Invalid instruction [expected link, reg or reg.link for jmp] -->"& mnemonic(mnemonic'left to lineends)
                  severity FAILURE;
              end if;
            elsif strcmp(mnemonic(pos),' ') then -- jmp
              opcode := "000000";
              instrtype := ZERO;
              -- don't increment the pos
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[jmp??] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.2)


          -- [4] LOAD IMM:
          ---------------- 
          elsif strcmp(mnemonic(pos to pos + 4), "LOADI") then  --==>> LOADI(1)    
            pos := pos + 5;   -- points to after loadi
            if strcmp(mnemonic(pos),'.') then -- hi or lo (1.2)
              if strcmp(mnemonic(pos+1 to pos+2),"hi") then -- hi
                opcode := "000100";
                pos := pos + 3; -- point to one after
                instrtype := ONE;
              elsif strcmp(mnemonic(pos+1 to pos+2),"lo") then -- lo
                opcode := "000101";
                pos := pos + 3;-- point to one after
                instrtype := ONE;
              else 
                errprnt(check, errstr, linenum); -- function to print error message and line no
                assert (FALSE)
                  report "Invalid instruction [expected hi or lo for loadi] -->"& mnemonic(mnemonic'left to lineends)
                  severity FAILURE;
              end if;
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[loadi?] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.2)
            
          -- [5] COMPARE :
          ---------------- 
          elsif strcmp(mnemonic(pos to pos + 2), "CMP") then  --==>> CMP(1)    
            opcode := "001000";
            pos := pos + 3;   -- points to after cmp
            if strcmp(mnemonic(pos),'.') then -- 10 choices of relation(1.2)
              if strcmp(mnemonic(pos+1 to pos+2),"eq") then -- eq
                tag := "0000";
                pos := pos + 3; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+2),"ne") then -- ne
                tag := "0001";
                pos := pos + 3; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+3),"ltu") then -- ltu
                tag := "0110";
                pos := pos + 4; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+3),"leu") then -- leu
                tag := "0111";
                pos := pos + 4; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+3),"gtu") then -- gtu
                tag := "1000";
                pos := pos + 4; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+3),"geu") then -- geu
                tag := "1001";
                pos := pos + 4; -- point to one after
              -- first the above ones should be checke o/w zicar
              elsif strcmp(mnemonic(pos+1 to pos+2),"lt") then -- lt
                tag := "0010";
                pos := pos + 3; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+2),"le") then -- le
                tag := "0011";
                pos := pos + 3; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+2),"gt") then -- gt
                tag := "0100";
                pos := pos + 3; -- point to one after
              elsif strcmp(mnemonic(pos+1 to pos+2),"ge") then -- ge
                tag := "0101";
                pos := pos + 3; -- point to one after
              else 
                errprnt(check, errstr, linenum); -- function to print error message and line no
                assert (FALSE)
                  report "Invalid instruction [expected rel for cmp.] -->"& mnemonic(mnemonic'left to lineends)
                  severity FAILURE;
              end if;
            else
              errprnt(check, errstr, linenum); -- function to print error message and line no
              assert (FALSE)
                report "Invalid instruction[cmp?] -->"& mnemonic(mnemonic'left to lineends)
                severity FAILURE;
            end if; -- end of (1.2)
            instrtype := FIVE_A;            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            -- [2] ORI:
          ------------ 
          elsif strcmp(mnemonic(pos to pos + 2), "ORI") then --ori --=>> (2)
            opcode := "XXXXXX";
            pos := pos + 3;

            --------LOTSA more HERE!!!!!!!!!!!1

          
          else
            errprnt(check, errstr, linenum); -- function to print error message and line no
            assert (FALSE)
              report "Invalid instruction -->"& mnemonic(pos to lineends)
              severity FAILURE;
          end if; -- END OF (1)
          --=============================================================
          ---------- END OF BIG INSTRUCTION READ LOOP --------------------
          --=============================================================

          --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          -- READ THE REGISTERS and IMMEDIATES: (and combine the final instr)  
          --vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

          if instrtype = ZERO then --(%)
            -- IMM 23 VALUE:
            ----------------
            Read_Imm(mnemonic, pos, immval, check, errstr, linenum, lineends);
            imm23 := std_logic_vector(to_signed(immval,23));

            ---------------------------------------------------------------------
            --  COMBINE THE FIELDS TO 32 BIT BINARY INSTRUCTION:
            ---------------------------------------------------------------------
            instr1 := predicate&opcode&IMM23;      
            ---------------------------------------------------------
            --Debugging option:
            write(check,instr1);
            writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------          

          elsif instrtype = ONE then
            -- Rd Register:
            ---------------
            Read_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rd := std_logic_vector(to_unsigned(regnum,5)); -- reads Rd correctly if reaches here!!
          
            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
            
            Read_Imm(mnemonic, pos, immval, check, errstr, linenum, lineends);
            imm18 := std_logic_vector(to_signed(immval,18));

            ---------------------------------------------------------------------
            --  COMBINE THE FIELDS TO 32 BIT BINARY INSTRUCTION:
            ---------------------------------------------------------------------
            instr1 := predicate&opcode&Rd&IMM18;      
            ---------------------------------------------------------
            --Debugging option:
            write(check,instr1);
            writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------          
            
          elsif instrtype = FOUR_A then
            -- Rd Register:
            ---------------
            Read_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rd := std_logic_vector(to_unsigned(regnum,5)); -- reads Rd correctly if reaches here!!
            ---------------------------------------------------------
            --Debugging option:
            --write(check,Rd);
            --writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------

            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
           
            -- Rs1 Register:
            ----------------
            Read_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rs1 := std_logic_vector(to_unsigned(regnum,5));
            ---------------------------------------------------------
            --Debugging option:
            --write(check,Rs1);
            --writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------

            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
  
            -- Rs2 Register:
            ----------------
            Read_LAST_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rs2 := std_logic_vector(to_unsigned(regnum,5));
            ---------------------------------------------------------
            --Debugging option:
            --write(check,Rs2);
            --writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------

            ---------------------------------------------------------------------
            --  COMBINE THE FIELDS TO 32 BIT BINARY INSTRUCTION:
            ---------------------------------------------------------------------
            instr1 := predicate&opcode&Rs1&Rs2&Rd&subop;      
            ---------------------------------------------------------
            --Debugging option:
            write(check,instr1);
            writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------          

          elsif instrtype = FIVE_A then
            -- Rs1 Register:
            ---------------
            Read_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rs1 := std_logic_vector(to_unsigned(regnum,5)); -- reads Rd correctly if reaches here!!
                
            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
            
            -- Rs2 Register:
            ----------------
            Read_Reg(mnemonic, pos, regnum, check, errstr, linenum, lineends);
            Rs2 := std_logic_vector(to_unsigned(regnum,5));

            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
            
            -- P1 Register:
            ---------------
            Read_PRED(mnemonic, pos, prednum, check, errstr, linenum, lineends);            
            P1 := std_logic_vector(to_unsigned(prednum,3));    
            
            Skip_comma(mnemonic, lineends, pos);  -- skip comma function to skip_comma
            
            -- P2 Register:
            ---------------
            Read_PRED(mnemonic, pos, prednum, check, errstr, linenum, lineends);            
            P2 := std_logic_vector(to_unsigned(prednum,3));    

            ---------------------------------------------------------------------
            --  COMBINE THE FIELDS TO 32 BIT BINARY INSTRUCTION:
            ---------------------------------------------------------------------
            instr1 := predicate&opcode&Rs1&Rs2&"000"&P1&P2&tag;      
            ---------------------------------------------------------
            --Debugging option:
            write(check,instr1);
            writeline(output,check); -- TO WRITE TO STANDARD OUTPUT
            ---------------------------------------------------------          
            
          end if; -- end of (%)
          --^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          -- END OF REGISTER and IMMEDIATE READ ---
          --vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

          

          --////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
          -- WRITE THE RESULTANT BINARY FILE:
          --////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
          write(writepoint,instr1);
          writeline(binaryinst, writepoint);
          --////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
          -- END OF WRITING THE BINARY FILE LINE
          --////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
              
        END IF; -- end of BIGGEST IF

      end loop readloop; -- END OF FILE READ LOOP
      TOPtestgoes <= FALSE; -- keyboard reading finished
      wait; -- NEEDED TO AVOID ZERO DELTA DELAY PROCESSOR, waits indefinitely
      
  end process assemble; --EOPROCESS
      
  --concurrent:
  assert (TOPtestgoes)
      report "test finished"
        severity FAILURE;      
   
end testbench; --EOArchitecture


