// Copyright 2000 UCR all rights reserved
// this program may be copy or altered so
// long as this header stays intake
// Original design Randy January rjanuary@cs.ucr.edu


/* main.cc
   Randy January
   file description: Assembler for simple CPU
*/

#include <fstream.h>
#include <stdlib.h>
#include <string.h>

void makeBinary(int, int);
ofstream outfile;


int main(int arg, char *argv[])
{
  char command[80];
  int cnt = -1;
  int imm;
  char operand[18];
  int i = 0;
  int reg;
  

  if (arg != 2)
    {
      cerr << "Usage: assemble <filename>";
      exit(-1);
    }
  else
    {   
      ifstream infile (argv[1], ios::in);
      if (!infile)
	{
	  cerr << "Error opening " << argv[1] << endl;
	  exit(-1);
	}
      outfile.open("scpu_rom.vhd", ios::out);
      
      while(infile)
	{
	  infile >> command;
	  
	 
	  if (strcmp(command, "loadi") == 0)
	      {
		cnt += 1;
	      }
	      
	  else if(strcmp(command, "add") == 0)
	      {
		cnt += 1;
	      }
	      
	  else if (strcmp(command, "sub") == 0)
	      {
		cnt += 1;
	      }
	      
	  else if(strcmp(command, "xor") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "and") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "or") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "shl") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "shr") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "jnz") == 0)
  	      {
  		cnt += 1;
  	      }

	  else if(strcmp(command, "jlz") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "store") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "loadm") == 0)
  	      {
  		cnt += 1;
  	      }
	      
  	  else if(strcmp(command, "mult") == 0)
  	      {
  		cnt += 6;
  	      }
	      
  	  else if(strcmp(command, "div") == 0)
  	      {
  		cnt += 0;
  	      }
	     
  	  else if(strcmp(command, "comp") == 0)
  	      {
  		cnt += 0;
  	      }
	      
  	  else if(strcmp(command, "equal") == 0)
  	      {
  		cnt += 0;
  	      }
	      
	  else if (strcmp(command, "halt") == 0)
	      {
		cnt += 1;
	      }
	    }
	
      
      
      outfile << "library IEEE;" << endl << "use IEEE.STD_LOGIC_1164.all;"
	      << endl << "use IEEE.STD_LOGIC_ARITH.all;" << endl
	      << "use WORK.SCPU_LIB.all;" << endl << endl
	      << "entity scpu_rom is" << endl << "\tport (" << endl
	      << "\t\trst     : in std_logic;" << endl
	      << "\t\tclk     : in std_logic;" << endl
	      << "\t\taddress : in integer;"   << endl
	      << "\t\tcommand : out unsigned (31 downto 0)" << endl
	      << "\t\t);" << endl << "end scpu_rom;" << endl
	      << "architecture beh of scpu_rom is" << endl
	      << "--************************************************" << endl
	      << "type ROM is array (0 to " << cnt 
	      << ") of unsigned (31 downto 0);" 
	      << endl << "constant program : ROM := (" << endl;
      
      infile.close();
      infile.open(argv[1], ios::in);
      cnt = 0;
      
      while(infile)
	{
	  infile >> command;
     
	  if (strcmp(command, "loadi") == 0)
	    {
	      outfile << "\"00000";

	      infile.getline(operand, 80, 'R');
	      infile >> reg;      
	      i = 8;
	      makeBinary(reg, i);
	      
	      i = 17;
	      infile >> imm;
	      makeBinary(imm, i);
	      outfile << "\"," << endl;
	      cnt += 1;
	      
	    }
	  
	  else if(strcmp(command, "add") == 0)
	    {
	      outfile << "\"00001";
	      for (int j = 0; j < 3; j++)
		{
		  
		  infile.getline(operand, 80, 'R');
		  infile >> reg;
		  i = 8;
		  makeBinary(reg, i);
		}
	      outfile << "\"," << endl;
	      cnt += 1;
	      
	    }
	  else if (strcmp(command, "sub") == 0)
	    {
	      outfile << "\"00010";
	      for (int j = 0; j < 3; j++)
		{ 
		  infile.getline(operand, 80, 'R');
		  infile >> reg;
		  i = 8;
		  makeBinary(reg, i);
		}
	      outfile << "\"," << endl;
	      cnt += 1;
	    }

	  else if (strcmp(command, "xor") == 0)
	    {
	      outfile << "\"00011";
	      for (int j = 0; j < 3; j++)
		{ 
		  infile.getline(operand, 80, 'R');
		  infile >> reg;
		  i = 8;
		  makeBinary(reg, i);
		}
	      outfile << "\"," << endl;
	      cnt += 1;
	    }

	  else if (strcmp(command, "and") == 0)
	    {
	      outfile << "\"00100";
	      for (int j = 0; j < 3; j++)
		{ 
		  infile.getline(operand, 80, 'R');
		  infile >> reg;
		  i = 8;
		  makeBinary(reg, i);
		}
	      outfile << "\"," << endl;
	      cnt += 1;
	    }

	   else if (strcmp(command, "shr") == 0)
	    {
	      outfile << "\"00101";
	      infile.getline(operand, 80, 'R');
	      infile >> reg;
	      i = 8;
	      makeBinary(reg, i);
	      outfile << "000000000000000000\"," << endl;
	      cnt += 1;
	    }

	  else if (strcmp(command, "shl") == 0)
	    {
	      outfile << "\"00110";
	      infile.getline(operand, 80, 'R');
	      infile >> reg;
	      i = 8;
	      makeBinary(reg, i);
	      outfile << "000000000000000000\"," << endl;
	      cnt += 1;
	    }

	  else if (strcmp(command, "or") == 0)
	    {
	      outfile << "\"00111";
	      for (int j = 0; j < 3; j++)
		{ 
		  infile.getline(operand, 80, 'R');
		  infile >> reg;
		  i = 8;
		  makeBinary(reg, i);
		}
	      outfile << "\"," << endl;
	      cnt += 1;
	    }

	  else if (strcmp(command, "jlz") == 0)
	    {
	      outfile << "\"01000";
	      outfile << "000000000";
	      infile.getline(operand, 80, 'R');
	      infile >> reg;      
	      i = 8;
	      makeBinary(reg, i);
	      i = 8;
	      infile >> imm;
	      makeBinary(imm, i);
	      outfile << "\"," << endl;
	      cnt += 1;
	    }
	  
	  else if (strcmp(command, "jnz") == 0)
	    {
	      outfile << "\"01001";
	      outfile << "000000000";
	      infile.getline(operand, 80, 'R');
	      infile >> reg;      
	      i = 8;
	      makeBinary(reg, i);
	      i = 8;
	      infile >> imm;
	      makeBinary(imm, i);
	      outfile << "\"," << endl;
	      cnt += 1;
	    }
	  
	   else if (strcmp(command, "store") == 0)
	    {
	      outfile << "\"01010";
	      
	      infile.getline(operand, 80, 'R');
	      infile >> reg;      
	      i = 8;
	      makeBinary(reg, i);
	      outfile << "000000000";
	      i = 8;
	      infile >> imm;
	      makeBinary(imm, i);
	      outfile << "\"," << endl;
	      cnt += 1;
	    }
	  
	   else if (strcmp(command, "loadm") == 0)
	    {
	      outfile << "\"01011";
	      
	      infile.getline(operand, 80, 'R');
	      infile >> reg;      
	      i = 8;
	      makeBinary(reg, i);
	      
	      i = 8;
	      infile >> imm;
	      makeBinary(imm, i);
	      outfile << "000000000\"," << endl;
	      cnt += 1;
	    }
	        
	  else if (strcmp(command, "halt") == 0)
	    {
	      outfile << "\"11111000000000000000000000000000\"" << endl;
	    }
	}
      outfile << ");" << endl;
      outfile << "--********************************************************"
	      << endl << endl << "begin" << endl 
	      << "\tprocess(rst, clk, address)" << endl
	      << "\t\tbegin" << endl << "\t\t\tif (rst = '1') then"
	      << endl << "\t\t\t\tcommand <= CD_32;" << endl
	      << "\t\telsif (clk'event and clk = '1') then" << endl
	      << "\t\t\t\tcommand <= program(address);" << endl
	      << "\t\t\tend if;" << endl
	      << "\t\tend process;" << endl
	      << "end beh;" << endl; 
      infile.close();
      outfile.close();
      
    }
  
}


void makeBinary(int value, int size)
{
  int binary[18];
  int i;

  i = size;
  
  while (value != 0)
    {
      if ((value + 1)/2 > value/2)
	{
	  binary[i] = 1;
	}
      else 
	{
	  binary[i] = 0;
	}
      i--;
      value = value/2;
    }
  
  while (i >= 0)
    {
      binary[i] = 0;
      i--;
    }
  
  i = 0;
  
  while (i < size + 1)
    {
      outfile << binary[i];
      i++;
    }
}

	        





