/***************************************************************************/
/*                            DATAPATH SIMULATOR                           */
/*                                                                         */
/*                              By Emily Ezust                             */
/*                                   1993				   */
/*                                                                         */
/*                 Based on Andrew Tanenbaum's hypothetical                */
/*                   Complex Instruction Set Computer                      */
/*                                                                         */
/***************************************************************************/

/***************************************************************/
/*                                                             */
/* Copyright (c) 1995 by Emily Ezust                           */
/*                                                             */
/* This software is hereby licensed for non-commercial use     */
/* only.  It may be freely distributed but it may not be used  */
/* for monetary profit.  Commercial use of this software is    */
/* not permitted without an explicit written agreement with    */
/* the author.                                                 */
/*                                                             */
/***************************************************************/


/* initialization module */
#include <stdio.h>
#include <signal.h>
#include <curses.h>
#include "constants.h"
#include "structs.h"

extern int scratch[SCRATCH_LENGTH] ;
extern screg screen_regs[NUM_DATA_POINTS] ;
extern point screen[24][80] ;
extern table_entry ct[23] ;
extern int pow2(int) ;
extern alu_info alu ;
extern int mc ;
extern int mir[INST_LENGTH] ;
extern char microcode[MAX_MICROCODE_SIZE][MAX_PSEUDOINST_LENGTH] ;

info *ialloc(void) 
{
  return (info *)malloc(sizeof(info)) ;
}

pair *palloc(void)
{
  return (pair *)malloc(sizeof(pair)) ;
}

plist *halloc(void) 
{
  return (plist *)malloc(sizeof(plist)) ;
}

void init_screen(void) 
{
  int i, j, k, rg ;
  point *ptr ;
  plist *trav ;
  
  for (i = 0; i <= 23; i++)
    for (j = 0; j <= 79; j++)  
      {
	ptr = &screen[i][j] ;
	ptr->chr = ' ' ;
	ptr->next = NULL ;
	ptr->alt = NULL ;
	ptr->data_changes = FALSE ;
	ptr->store_data = FALSE ;
	ptr->screg_index = 0 ;
	ptr->reg_ptr = NULL ;
	ptr->circ = 0 ;
	ptr->highlights = NULL ;
	ptr->take_both_paths = FALSE ;
      }
  screen[0][2].chr = 'B' ;
  for (j = 3; j <= 56 ; j++) 
    {
      screen[0][j].chr = '-' ;
      screen[0][j].next = palloc() ;
      screen[0][j].next->r = 0 ;
      screen[0][j].next->c = j + 1 ;
    }
  screen[0][47].chr = 'B' ;
  screen[0][50].alt = ialloc() ;
  screen[0][50].alt->alt = palloc() ;
  screen[0][50].alt->alt->r = 1 ;
  screen[0][50].alt->alt->c = 50 ;
  screen[0][50].take_both_paths = TRUE ;

  screen[0][56].chr = '\\' ;
  screen[0][56].next->r = 1 ;
  for (i = 1; i <= 3; i++)
    for (j = 5; j <= 45; j +=4) 
      {
	screen[i][j].chr = '|' ;
	screen[i][j].next = palloc() ;
	screen[i][j].next->r = i - 1 ;
	screen[i][j].next->c = j ;
      }
  screen[1][57].chr = '\\' ;
  screen[2][58].chr = '\\' ;
  screen[1][57].next = palloc() ;
  screen[2][58].next = palloc() ;
  screen[1][57].next->r = 2 ;
  screen[1][57].next->c = 58;
  screen[2][58].next->r = 2 ;
  screen[2][58].next->c = 59 ;
  for (j = 59; j <= 62; ++j) 
    {
      screen[2][j].chr = '_' ;
      screen[2][j].next = palloc() ;
      screen[2][j].next->r = 2 ;
      screen[2][j].next->c = j+1;
    }
  screen[2][63].chr = 'A' ;
  screen[2][63].reg_ptr = &scratch[ALU_B] ;
  screen[2][63].store_data = TRUE ;    /* this loads B latch for ALU */
           /* this is the end of the path for B-bus data flow. */
  screen[2][63].screg_index = SCREEN_ALU_F ;
  for (j = 63; j <= 71; j++) 
    {
      screen[3][j].chr = '-' ;
      screen[3][j].next = palloc() ;
      screen[3][j].next->r = 3 ;
      screen[3][j].next->c = j + 1 ;
    }
  screen[3][63].chr = 'L' ;
  screen[3][63].circ = 1 ;
  screen[3][63].reg_ptr = &scratch[ALU] ;
  screen[3][63].data_changes = TRUE ;
  screen[3][63].screg_index = SCREEN_ALU_NZ ;
  screen[0][67].chr = 'S' ;
  screen[1][67].chr = 'H' ;
  screen[2][67].chr = 'I' ;
  screen[3][67].chr = 'F' ;
  screen[4][67].chr = 'T' ;
  screen[5][67].chr = 'E' ;
  screen[6][67].chr = 'R' ;
  screen[3][67].screg_index = SCREEN_SHIFTER ;
  screen[3][67].reg_ptr = &scratch[SHIFTER] ;
  screen[3][67].data_changes = TRUE ;
  screen[3][67].store_data = TRUE ;
  screen[3][67].circ = 2 ;
  for (i = 1; i <= 21 ; i++) 
    {
      screen[i][50].chr = '|' ;
      screen[i][50].next = palloc() ;
      screen[i][50].next->r = i + 1 ;
      screen[i][50].next->c = 50 ;
    }
  screen[1][50].alt = ialloc() ;
  screen[1][50].alt->alt = palloc() ;
  screen[1][50].alt->alt->r = 2 ;
  screen[1][50].alt->alt->c = 50 ;
  free(screen[1][50].next) ;
  screen[1][50].next = NULL ;
  screen[1][50].alt->inst_ind = MAR_IND ;
  screen[1][50].alt->match = 1 ;

  screen[3][50].next->r = 5 ;
  screen[13][50].next->r = 15 ;
  screen[16][50].next->r = 18 ;
  screen[16][50].chr = 'R' ;
  screen[16][50].screg_index = MAR ;
  screen[16][50].reg_ptr = &scratch[MAR] ;
  screen[16][50].store_data = TRUE ;
  screen[17][50].reg_ptr = &scratch[MAR] ;
  screen[17][50].data_changes = TRUE ;   /* starts here for memory access */
  free(screen[21][50].next) ;
  screen[21][50].next = NULL ;
  for (j = 2 ; j <= 56 ; j++) 
    {
      screen[4][j].chr = '-' ;
      screen[4][j].next = palloc() ;
      screen[4][j].next->r = 4 ;
      screen[4][j].next->c = j + 1 ;
    }
  screen[4][2].chr = 'A' ;
  screen[4][47].chr = 'A' ;
  screen[3][56].chr = 'A' ;
  screen[4][56].chr = 'M' ;
  screen[4][56].next->r = 5 ;
  for (j = 59; j <= 63; j++) 
    {
      screen[4][j].chr = '_' ;
      screen[4][j].next = palloc() ;
      screen[4][j].next->r = 4 ;
      screen[4][j].next->c = j + 1;
    }
  screen[4][63].chr = 'U' ;
  screen[4][63].next->r = 3 ;
  screen[4][63].next->c = 63 ;
  screen[4][63].reg_ptr = &scratch[ALU_A] ;
  screen[4][63].store_data = TRUE ;
  screen[4][63].screg_index = ALU_A ;
  for (i = 3; i <= 16; i++) 
    {
      screen[i][71].chr = '|' ;
      screen[i][71].next = palloc() ;
      screen[i][71].next->r = i + 1 ;
      screen[i][71].next->c = 71 ;
    }
  screen[14][71].next->r = 14 ;
  screen[14][71].next->c = 70 ;
  screen[14][71].alt = ialloc() ;
  screen[14][71].alt->alt = palloc() ;
  screen[14][71].alt->alt->r = 15 ;
  screen[14][71].alt->alt->c = 71 ;
  screen[14][71].alt->inst_ind = MBR_IND ;
  screen[14][71].alt->match = 1 ;
  screen[16][71].next->r = 16 ;
  screen[16][71].next->c = 70 ;
  for (i = 5; i <= 8; ++i)
    for (j = 3; j <= 43; j+=4) 
      {
	screen[i][j].chr = '|' ;
	screen[i][j].next = palloc() ;
	screen[i][j].next->r = i - 1 ;
	screen[i][j].next->c = j ;
      }
  for (j = 5; j <= 45; j += 4) 
    {
      screen[5][j].chr = '|' ;
      screen[5][j].next = palloc() ;
      screen[5][j].next->r = 3 ;
      screen[5][j].next->c = j ;
    }
  for (i = 6 ; i <= 8; i++)
    for (j = 5; j <= 45; j += 4) 
      {
	screen[i][j].chr = '|' ;
	screen[i][j].next = palloc() ;
	screen[i][j].next->r = i - 1 ;
	screen[i][j].next->c = j ;
    }
  screen[5][56].chr = 'U' ;
  screen[5][57].chr = '-' ;
  screen[5][57].next = palloc() ;
  screen[5][57].next->r = 5 ;
  screen[5][57].next->c = 58 ;
  screen[5][58].chr = '/' ;
  screen[5][58].next = palloc() ;
  screen[5][58].next->r = 4 ;
  screen[5][58].next->c = 59 ;
  for (j = 52 ; j <= 56; j++)  
    {
      screen[6][j].chr = '-';
      screen[6][j].next = palloc() ;
      screen[6][j].next->r = 6 ;
      screen[6][j].next->c = j + 1 ;
    }
  screen[6][52].chr = '|' ;
  screen[6][56].chr = 'X' ;
  screen[6][56].next->r = 5 ;
  for (i = 7; i <= 16; i++) 
    {
      screen[i][52].chr = '|' ;
      screen[i][52].next = palloc() ;
      screen[i][52].next->r = i - 1 ;
      screen[i][52].next->c = 52 ; 
    }
  screen[15][52].next->r = 13 ;
  screen[16][52].chr = 'M' ;
  screen[16][52].screg_index = MBR ;
  screen[16][52].reg_ptr = &scratch[MBR] ;
  screen[16][52].data_changes = TRUE ;
  screen[17][52].data_changes = TRUE ;
  screen[17][52].reg_ptr = &scratch[MBR] ;
  screen[21][52].circ = 4 ;
  screen[21][52].next = NULL ;

  for (i = 17; i <= 20 ; ++i) 
    {
      screen[i][52].next = palloc() ;
      screen[i][52].next->r = i + 1 ;
      screen[i][52].next->c = 52 ;
      screen[i][52].chr = '|' ;
    }
  screen[21][52].chr = '|' ;
  for (j = 3; j <= 45; j++)
    for (k = 1; k <= 3; k++)
      screen[9][j++].chr = '-' ;
  for (j = 3; j <=45; j+=2) 
    {
      screen[10][j].next = palloc() ;
      screen[10][j].next->r = 8 ;
      screen[10][j].next->c = j ;
      screen[10][j].data_changes = TRUE ;
    }
  for (j = 4; j <= 44; j+=4)
    screen[10][j].store_data = TRUE ;
  screen[10][3].chr = 'P' ;
  screen[10][4].chr = 'C' ;
  for (i=3, rg = PC; rg <= A_REG; rg++, i+=4)  
    for (j = i; j <= i + 2; j++) 
      screen[10][j].reg_ptr = &scratch[rg] ;
  screen[10][4].screg_index = PC ;
  screen[10][7].chr = 'A' ;
  screen[10][8].chr = 'C' ;
  screen[10][8].screg_index = AC ;
  screen[10][11].chr = 'S' ;
  screen[10][12].chr = 'P' ;
  screen[10][12].screg_index = SP ;
  screen[10][15].chr = 'I' ;
  screen[10][16].chr = 'R' ;
  screen[10][16].screg_index = IR ;
  screen[10][19].chr = 'T' ;
  screen[10][20].chr = 'I' ;
  screen[10][20].screg_index = TIR ;
  screen[10][21].chr = 'R' ;
  screen[10][24].chr = '0';
  screen[10][27].chr = '+' ;
  screen[10][28].chr = '1' ;
  screen[10][31].chr = '-' ;
  screen[10][32].chr = '1' ;
  screen[10][35].chr = 'A' ;
  screen[10][36].chr = 'M' ;
  screen[10][37].chr = 'K' ;
  screen[10][36].screg_index = AMASK ;
  screen[10][39].chr = 'S' ;
  screen[10][40].chr = 'M' ;
  screen[10][41].chr = 'K' ;
  screen[10][40].screg_index = SMASK ;
  screen[10][44].chr = 'A' ;
  screen[10][44].screg_index = A_REG ;
  for (i = 11; i <= 13; i++) 
    for (j = 4; j <= 44; j+= 4) 
      {
	screen[i][j].chr = '|' ;
	screen[i][j].next = palloc() ;
	screen[i][j].next->r = i - 1 ;
	screen[i][j].next->c = j ;
      }
  screen[14][2].chr = 'C' ;
  for (j = 3; j <= 69; j++) 
    {
      screen[14][j].chr = '-' ;
      screen[14][j].next = palloc() ;
      screen[14][j].next->r = 14 ;
      screen[14][j].next->c = j - 1;
    }
  screen[14][70].chr = '-' ;
  screen[14][70].alt = ialloc() ;
  screen[14][70].alt->alt = palloc() ;
  screen[14][70].alt->alt->r = 14 ;
  screen[14][70].alt->alt->c = 69 ;
  screen[14][70].alt->match = 1 ;
  screen[14][70].alt->inst_ind = ENC_IND ;
  for (rg = 0, j = 4; j <= 44; j+=4, rg++)
    {
      screen[14][j].alt = ialloc() ;
      screen[14][j].alt->alt = palloc() ;
      screen[14][j].alt->alt->r = 13 ;
      screen[14][j].alt->alt->c = j ;
      screen[14][j].alt->inst_ind = C_BUS_IND ;
      screen[14][j].alt->match = rg ;
    }
  screen[16][54].reg_ptr = &scratch[MBR] ;
  screen[16][54].screg_index = MBR ;
  screen[16][54].store_data = TRUE ;
  screen[16][54].next = NULL ;
  for (j = 55; j <= 70; j++) 
    {
      screen[16][j].chr = '-' ;
      screen[16][j].next = palloc() ;
      screen[16][j].next->r = 16 ;
      screen[16][j].next->c = j - 1 ;
    }
  for (i = 17; i <= 21; i++) 
    {
      screen[i][54].chr = '|' ;
      screen[i][54].next = palloc() ;
      screen[i][54].next->r = i - 1 ;
      screen[i][54].next->c = 54 ;
    }
  screen[21][54].circ = 3;

/* highlights: */

/* registers PC thru A_REG: */

  for (i = 3; i <= 45; i+= 4) 
    {
      screen[10][i].highlights = halloc() ;
      for (k = i, trav = screen[10][i].highlights; k <= i + 2; k++,
	   trav = trav->next) 
	{
	  trav->coords = palloc() ;
	  trav->coords->r = 10 ;
	  trav->coords->c = k ;
	  if (k < i + 2)
	    trav->next = halloc() ;
	  else
	    trav->next = NULL ;
	}
      screen[10][i+1].highlights = screen[10][i].highlights ;
      screen[10][i+2].highlights = screen[10][i].highlights ;
    }

  /* ALU */

  screen[2][63].highlights = halloc() ;
  for (i = 2, trav = screen[2][63].highlights ; i <= 4; i++,
       trav = trav->next) 
    {
      trav->coords = palloc() ;
      trav->coords->r = i ;
      trav->coords->c = 63 ;
      if (i < 4)
	trav->next = halloc() ;
      else
	trav->next = NULL ;
    }
  screen[4][63].highlights = screen[2][63].highlights ;
  
/* SHIFTER */

  screen[3][67].highlights = halloc() ;
  trav = screen[3][67].highlights ;
  for (i = 0; i <= 6; i++, trav = trav->next) 
    {
      trav->coords = palloc() ;
      trav->coords->r = i ;
      trav->coords->c = 67 ;
      if (i < 6)
	trav->next = halloc() ;
      else
	trav->next = NULL ;
    }

/* MAR */
  screen[16][48].chr = 'M' ;
  screen[16][49].chr = 'A' ;
  screen[17][50].highlights = halloc() ;
  trav = screen[17][50].highlights ;
  for (j = 48; j <= 50; j++, trav = trav->next)
    {
      trav->coords = palloc() ;
      trav->coords->r = 16 ;
      trav->coords->c = j ;
      if (j == 50)
	trav->next = NULL ;
      else
	trav->next = halloc() ;
    }
  screen[16][50].highlights = screen[17][50].highlights ;
  
/* MBR */
  screen[16][53].chr = 'B' ;
  screen[16][54].chr = 'R' ;
  screen[16][52].highlights = halloc() ;
  trav = screen[16][52].highlights ;
  for (j = 52; j <= 54; j++, trav = trav->next)
    {
      trav->coords = palloc() ;
      trav->coords->r = 16 ;
      trav->coords->c = j ;
      if (j < 54)
	trav->next = halloc() ;
      else
	trav->next = NULL ;
    }
  screen[16][54].highlights = screen[16][52].highlights ;
  screen[17][52].highlights = screen[16][52].highlights ;

/* register contents */
  screen[15][4].chr = 'M' ;
  screen[15][5].chr = 'I' ;
  screen[15][6].chr = 'R' ;
  screen[15][7].chr = ':' ;
  
  screen[16][3].chr = 'P' ;
  screen[16][4].chr = 'C' ;
  screen[16][5].chr = ':' ;
  
  screen[16][24].chr = 'S' ;
  screen[16][25].chr = 'M' ;
  screen[16][26].chr = 'K' ;
  screen[16][27].chr = ':' ;
  
  screen[17][3].chr = 'A' ;
  screen[17][4].chr = 'C' ;
  screen[17][5].chr = ':' ;

  screen[17][26].chr = 'A' ;
  screen[17][27].chr = ':' ;

  screen[18][3].chr = 'S' ;
  screen[18][4].chr = 'P' ;
  screen[18][5].chr = ':' ;

  screen[18][24].chr = 'M' ;
  screen[18][25].chr = 'A' ;
  screen[18][26].chr = 'R' ;
  screen[18][27].chr = ':' ;

  screen[19][3].chr = 'I' ;
  screen[19][4].chr = 'R' ;
  screen[19][5].chr = ':' ;

  screen[19][24].chr = 'M' ;
  screen[19][25].chr = 'B' ;
  screen[19][26].chr = 'R' ;
  screen[19][27].chr = ':' ;

  screen[20][2].chr = 'T' ;
  screen[20][3].chr = 'I' ;
  screen[20][4].chr = 'R' ;
  screen[20][5].chr = ':' ;

  screen[21][2].chr = 'A' ;
  screen[21][3].chr = 'M' ;
  screen[21][4].chr = 'K' ;
  screen[21][5].chr = ':' ;

  screen[21][24].chr = 'M' ;
  screen[21][25].chr = 'P' ;
  screen[21][26].chr = 'C' ;
  screen[21][27].chr = ':' ;

/* On-screen Data */

  screen[12][55].chr = 'D' ;
  screen[12][56].chr = 'a' ;
  screen[12][57].chr = 't' ;
  screen[12][58].chr = 'a' ;
  screen[12][59].chr = ':' ;
}

void init_ct(void)
{
  ct[0].code = 0;
  ct[1].code = pow2(12) ;
  ct[2].code = pow2(13) ;
  ct[3].code = pow2(12) + pow2(13) ;
  ct[4].code = pow2(14) ;
  ct[5].code = pow2(14) + pow2(12) ;
  ct[6].code = pow2(14) + pow2(13) ;
  ct[7].code = pow2(14) + pow2(13) + pow2(12) ;
  ct[8].code = pow2(15) ;
  ct[9].code = pow2(15) + pow2(12) ;
  ct[10].code = pow2(15) + pow2(13) ;
  ct[11].code = pow2(15) + pow2(13) + pow2(12) ;
  ct[12].code = pow2(15) + pow2(14) ;
  ct[13].code = pow2(15) + pow2(14) + pow2(12) ;
  ct[14].code = pow2(15) + pow2(14) + pow2(13) ;
  ct[15].code = pow2(15) + pow2(14) + pow2(13) + pow2(12) ;
  ct[16].code = ct[15].code + pow2(9) ;
  ct[17].code = ct[15].code + pow2(10) ;
  ct[18].code = ct[15].code + pow2(9) + pow2(10) ;
  ct[19].code = ct[15].code + pow2(11) ;
  ct[20].code = ct[19].code + pow2(9) ;
  ct[21].code = ct[19].code + pow2(10) ;
  ct[22].code = ct[21].code + pow2(9) ;
}

void init_scregs(void) 
{
  int i ;
  
  for (i = 0 ; i < NUM_DATA_POINTS; i++)
    screen_regs[i].coords = palloc() ;
  screen_regs[PC].coords->r = 16 ;
  screen_regs[PC].coords->c = 7 ;
  screen_regs[PC].data = &scratch[PC] ;
  screen_regs[AC].coords->r = 17 ;
  screen_regs[AC].coords->c = 7 ; 
  screen_regs[AC].data = &scratch[AC] ;
  screen_regs[SP].coords->r = 18 ;
  screen_regs[SP].coords->c = 7 ;
  screen_regs[SP].data = &scratch[SP];
  screen_regs[IR].coords->r = 19 ;
  screen_regs[IR].coords->c = 7 ;
  screen_regs[IR].data = &scratch[IR] ;
  screen_regs[TIR].coords->r = 20 ;
  screen_regs[TIR].coords->c = 7 ;
  screen_regs[TIR].data = &scratch[TIR] ;
  screen_regs[AMASK].coords->r = 21 ;
  screen_regs[AMASK].coords->c = 7 ;
  screen_regs[AMASK].data = &scratch[AMASK] ;
  screen_regs[SMASK].coords->r = 16 ;
  screen_regs[SMASK].coords->c = 30 ;
  screen_regs[SMASK].data = &scratch[SMASK] ;
  screen_regs[A_REG].coords->r = 17 ;
  screen_regs[A_REG].coords->c = 30 ;
  screen_regs[A_REG].data = &scratch[A_REG] ;
  screen_regs[MAR].coords->r = 18 ;
  screen_regs[MAR].coords->c = 30 ;
  screen_regs[MAR].data = &scratch[MAR] ;
  screen_regs[MBR].coords->r = 19 ;
  screen_regs[MBR].coords->c = 30 ;
  screen_regs[MBR].data = &scratch[MBR] ;  
  screen_regs[SCREEN_MIR].coords->r = 15 ;
  screen_regs[SCREEN_MIR].coords->c = 9 ;
  screen_regs[SCREEN_MIR].data = 0 ; 
  screen_regs[SCREEN_MPC].coords->r = 21 ;
  screen_regs[SCREEN_MPC].coords->c = 30 ;
  screen_regs[SCREEN_MPC].data = &mc ;
  screen_regs[SCREEN_ALU_F].coords->r = 1 ;
  screen_regs[SCREEN_ALU_F].coords->c = 63 ;
  screen_regs[SCREEN_ALU_F].data = 0 ;
  screen_regs[SCREEN_ALU_NZ].coords->r = 5 ;
  screen_regs[SCREEN_ALU_NZ].coords->c = 63 ;
  screen_regs[SCREEN_ALU_NZ].data = 0 ;
  screen_regs[SCREEN_SHIFTER].coords->r = 8 ;
  screen_regs[SCREEN_SHIFTER].coords->c = 67 ;
  screen_regs[SCREEN_SHIFTER].data = 0 ;
}

void init_coord_array(pair array[]) 
{
  int i;
  
  for (i = 0; i <= 12; i++)
    array[i].r = 4 ;
  array[0].c =  7 ;
  array[1].c = 11 ;
  array[2].c = 15 ;
  array[3].c = 19 ;
  array[4].c = 26 ;
  array[5].c = 30 ;
  array[6].c = 34 ;
  array[7].c = 38 ;
  array[8].c = 42 ;
  array[9].c = 49 ;
  array[10].c = 54 ;
  array[11].c = 59 ;
  array[12].c = 64 ;
}

void init_alu(void) 
{
  alu.F = &mir[ALU_IND] ; 
}

void init_pseudo(void) 
{
  int i;
  
  for (i = 0; i < MAX_MICROCODE_SIZE; i++)
    microcode[i][0] = '\0' ;
}
