
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define O_BINARY 0

#define NWindows 50
#define NRegs 22*NWindows+10
#define MaxNInstrs 10000	/* 1000 */
#define MaxSyms 1000	  /* 100 */

#define StartUserArgs 4

#define REG_TO_REG 1
#define LOAD_STORE 2
#define CONTROL_XFER 3
#define TWO_OPERAND 11
#define ONE_REG 12
#define ONE_CONST 13
#define ZERO_OPERAND 14	

#define CONST_TO_REG 15		/* KDR : for sethi */

#define OP2_IS_REG 21
#define OP2_IS_CONST 22
#define LT 31
#define LE 32
#define EQ 33
#define GE 34
#define GT 35
#define NE 36
#define NONE 37
#define READ 41
#define WRITE 42
#define AINC 43
#define TAS 44


#define USER 0
#define PRAM 1
#define BUS 2
#define XBAR 3
#define OMEGA 4
#define SNOOPY_UPDATE 5
#define SNOOPY_INVALIDATE 6


#define PERR(lnum,l) printf("   at line %d in .mas -->    %s\n",lnum,l)
#define PERR2(lnum,l) printf("   at line 0x%x (%d) in .lst check -->   %s\n",lnum,lnum,l)

extern int CurrLineNum;        /* current line number of the .mas file
				  used for error messages */



struct InstrStruct  {
   char Label[32],  /* assembly-language label for this instruction */
        AsmblSrcLine[240],  /* assembly-language source for current 
                              instruction */
        Mnemonic[32];  /* op code mnemonic */
   unsigned InstrGrp,  /* REG_TO_REG, LOAD_STORE, or CONTROL_XFER */
            SecondOpType,  /* (REG_TO_REG) OP2_IS_REG or OP2_IS_CONST */
	    Base,  /* LOAD_STORE base value */
	    JumpTarget,  /* (CONTROL_XFER) absolute address of target */
	    Condition,  /* (CONTROL_XFER) LT, LE, EQ, GE or GT */
	    RS1,RS2,RD;  /* rs1, rs2, rsd register numbers, all window-relative */
   unsigned Const;  /* possible REG_TO_REG Operand 2 */
};


struct CPUStruct  {
   char CondCodes[2],  /* Z,N flags */
            Disp[32];  /* the j-th one is `d', `f' or `x' if (relative) 
	                  register j is to be displayed in hex or float 
			  form at pauses of MulSim; 0 otherwise */
   unsigned Reg[NRegs],  /* register file (the whole set, not just one 
                            window) */
            Op2,  /* second operand of current REG_TO_REG instruction */
	    MemValue,  /* if READ, then the value read from memory; 
		          if WRITE, then the value to be written to 
			  memory; if AINC, then the value stored in 
			  memory prior to the incrementation; if TAS,
			  then the TAS return value */
            PC,  /* program counter */
            OldPC,  /* old PC value, for debugging help */
	    Halted,  /* 1 if CPU is in halt state */
            CWP,  /* absolute number of virtual-register 16 of the 
                     current window */
	    EffAddrs,  /* effective address of current LOAD_STORE
                          instruction (dynamically determined) */
            AbsRS1,AbsRS2,AbsRD,  /* absolute, i.e. non-window-relative,
     	                             register numbers for rs1, rs2, rd 
                                     of current instruction (dynamically 
				     determined) */
            MemAccPending,  /* 1 or 0, according to whether a memory access 
	                       is pending */
            MemAccType,  /* READ, WRITE, AINC or TAS */
            DispAny;  /* 1 if at least one Disp[J] is nonzero, otherwise 0 */
 }; 
			     

struct TableEntry  {
   char Symbol[32];
   unsigned Location;
};


struct MemAccStruct  {
   int PNum,  /* number of the CPU which issued the request */
       Dest;  /* destination, e.g. memory module number, CPU
                 number, network node number, etc. */
   unsigned ArrivalTime;  /* earliest simulated time at which the
                             request will reach its destination
			     (could be later, e.g. if this request
			     clashes with another at a node) */
   struct MemAccStruct *Next;
};


extern struct TableEntry SymTable[MaxSyms];


extern struct CPUStruct *CPU;  /* CPU[I] contains the status of the
                                  I-th CPU */


typedef struct MemAccStruct *MemAccPtr;


struct RouterStruct{
  MemAccPtr RoutHead;
  MemAccPtr RoutTail;
  MemAccPtr LoutHead;
  MemAccPtr LoutTail;
  MemAccPtr ToutHead;
  MemAccPtr ToutTail;
  MemAccPtr BoutHead;
  MemAccPtr BoutTail;
};


typedef struct RouterStruct *RouterPtr;


/* used for the crossbar and possibly some user-defined interconnects: */

extern MemAccPtr *MemInHead,  /* MemInHead[I] is the pointer to the head
                                 of the queue of messages from the CPUs
				 to the I-th memory module */
                 *MemInTail,
                 *MemOutHead,  /* same, but from memory modules to CPUs */
                 *MemOutTail,
                 NewMemRequestsHead,  /* new requests which must now be added
		                         to MemIn */
                 NewMemRequestsTail;

/* used for the crossbar and omega interconnects */
extern RouterPtr	**Routers,	/* number of routers in system */
			*PE;		/* the PE's in the system */
extern int PE_UPDATE;

/* used for omega */
extern int 	Stages,  		/*number of stages in the network */
				NodesPerStage;	/* number of routers in each stage */


extern unsigned *Mem;  /* this is the shared memory, with Mem[I]
                          being the word at address I */


extern unsigned SimTime;  /* current simulated time, i.e. number of 
                             cycles elapsed so far */


extern char ProgName[25],  /* program name */
            Cmndv[100][32],  /* user command, changed from 5 to
                                100 2/7/99, NM */
            Argv[10][32];  /* copy of argv from main() */


extern int Cmndc,  /* number of arguments in Cmndv */
           InterconType,  /* type of processor-memory interconnect */
	   Interactive,  /* 1 if doing interactive debugging, 0 if doing
	                      straight run */
           NHalted,  /* number of CPUs currently halted */
	   Stop,
           ProgLength,  /* number of instructions in the program */
           MemSize,  /* number of words in MulSim's memory */
           NCPUs,  /* number of CPUs */  
	   NDataSyms,  /* number of data symbols, in MulSim.c */
           Argc;  /* copy of argc from main() */

	   
extern struct InstrStruct Instr[MaxNInstrs],*ISPtr;


extern unsigned NamedLongGet(),LongRegValue(),LongValue();


extern float NamedFloatGet(),FloatRegValue(),FloatValue();


/* for the snoopy-update MAF */
extern int NoWritesYet;  /* equal to 1 if no writes have been done yet 
                            in this cycle */


/* for the snoopy-invalidate MAF */
extern char *StatePtr;
extern unsigned BlockXferTimeLeft,  /* number of cycles left for 
                                       the current block transfer */
                *ExclPNum,   /* ExclPNum[B] is the number of the
                                processor, if any which is in 
				Exclusive state for block B (equal 
				to -1 if none) */
                NBlocks,  /* total number of blocks in MulSim's memory */
	        BlockSize,  /* number of words in one memory block */
	        NoBusUseFoundYet,  /* equal to 1 if the bus has not yet 
		                      been used in this cycle */
                StartPNum;  /* number of CPU currently having the
                               first priority for bus usage */
extern int InvalPNum,  /* number of the Invalid-state processor
                          to which a block xfer is being done */
    XferBNum;  /* block number for which a xfer is being done */





