⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ms_ldst.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	entry->invalidated = 0;	entry->loadhit = NULL;	vs = entry->validBytes;	vs[0] = 0; vs[1] = 0; vs[2] = 0; vs[3] = 0;	vs[4] = 0; vs[5] = 0; vs[6] = 0; vs[7] = 0;		/* If we are allocating a load see if a previous store	*/		/* can provide us with a value.				*/	if (IsLoad(lstype))		{		int off = (paddr & 7);		int size = LdSizeOf(lstype);		int anyhit = 0;		int b, hitflag;		store1 = store2 = NULL;		for (entry = entry->prev; (entry); entry = prev_entry)			{			prev_entry = entry->prev;			if (!IsStore(entry->ls->lstype)) continue;			if (((entry->paddr)&~7) == (paddr&~7))				{				if (store1 == NULL)					store1 = entry;				else					{					store2 = entry;					break;					}				}			}		entry = st->ldst_tail;	 /*	JEB:  Address and size could be inconsistent at this point,	  *	due to speculation.  As a later enhancement, detect this	  *	case and use this as a hint to stop fetching along this	  *	thread, and activate a different one.  Put the check earlier	  *	in the pipeline, where the TLB translation is currently.	  */		if ((size+off) > 8) size = 8 - off;		if (store1)			{			hitflag = 1;			for (b = 0; b < size; b++)				{				if (store1->validBytes[b+off])					anyhit = 1;				else					{ hitflag = 0; }				}			if (hitflag) entry->loadhit = store1;			if (anyhit) return (entry);			}		if (store2)			{			hitflag = 1;			for (b = 0; b < size; b++)				if (!store2->validBytes[b+off])					{ hitflag = 0;  break; }			if (hitflag) entry->loadhit = store2;			}		}	return (entry);	}	/*	 *  ldst_buffer_reserve  -  Reserve an entry in ldst_buffer	 *	 *	Returns -1 if reservation fails	 */int ldst_buffer_reserve (struct s_cpu_state *st)	{	struct s_ldst_buffer *entry;	entry = st->ldst_nextAvail;	if (entry)		{	/* Found a free entry.  Move it to the reserved	*/			/* list.					*/		st->ldst_nextAvail = entry->next;		entry->next = st->ldst_nextReserved;		st->ldst_nextReserved = entry;		return (0);		}	return (-1);	}	/*	 *  ldst_buffer_release  -  Release a reserved entry	 */void ldst_buffer_release (struct s_cpu_state *st)	{	struct s_ldst_buffer *entry = st->ldst_nextReserved;	if (entry)		{	/* Move entry from reserved list to free list	*/		st->ldst_nextReserved = entry->next;		entry->next = st->ldst_nextAvail;		st->ldst_nextAvail = entry;		}#ifdef DEBUG_CHECKS	else		{		fprintf (stderr, "Illegal release of ldst_buffer entry\r\n");		ms_break (st, NULL, "ERR");		}#endif	}	/*	 *  ldst_buffer_free  -  Free the given load store buffer entry	 */static void ldst_buffer_free (struct s_cpu_state *st,					struct s_ldst_buffer *entry)	{	struct s_ldst_buffer *scan;		/* If it's a store, check if any loads are depending	*/		/* on this value.  Then let them know it is gone.	*/	if (IsStore (entry->ls->lstype))		{		for (scan = st->ldst_head; (scan); scan = scan->next)			{			if ((scan->loadhit == entry) &&			    IsLoad (scan->ls->lstype) )				{				scan->loadhit = NULL;					/* Turn off LS_ST_CACHED so	*/					/* it will be retried in cache	*/				scan->ls->status &= ~(LS_ST_PEND|LS_ST_CACHED);				}			}		}		/* Move the entry from the active list to the free list	*/	if (entry->prev == NULL)		st->ldst_head = entry->next;	else		entry->prev->next = entry->next;	if (entry->next == NULL)		st->ldst_tail = entry->prev;	else		entry->next->prev = entry->prev;	entry->next = st->ldst_nextAvail;	st->ldst_nextAvail = entry;	}	/*	 *  ldst_buffer_write  -  Write data into the given entry in the	 *	load/store buffer and mark the set bytes valid.	 *	 *	If invalid arguments are passed, it is due to a speculative	 *	write.  This is OK, just return silently.	 *	 *	JEB: As a later enhancement, could use this as a hint to stop	 *	fetching along this thread, and activate a different one.	 */static void ldst_buffer_write(struct s_cpu_state *st,	struct s_ldst_buffer *entry, int paddr, char *data,int size){   int lineoffset;   if (size > 8) fprintf(stderr, "Memory op large\r\n");   entry->paddr = paddr;   entry->size = size;   lineoffset = paddr & 7;   if ((size+lineoffset) > 8) size = 8 - lineoffset;   switch(size) {   case 1:	*(char *) (entry->data + lineoffset) = *(unsigned char*)data;	*(char *) (entry->validBytes + lineoffset) = 1;	break;   case 2:	*(char *) (entry->data + lineoffset+0) = *(unsigned char*)data;	*(char *) (entry->data + lineoffset+1) = *(unsigned char*)(data+1);	*(char *) (entry->validBytes + lineoffset+0) = 1;	*(char *) (entry->validBytes + lineoffset+1) = 1;	break;   case 3:	*(char *) (entry->data + lineoffset+0) = *(unsigned char*)data;	*(char *) (entry->data + lineoffset+1) = *(unsigned char*)(data+1);	*(char *) (entry->data + lineoffset+2) = *(unsigned char*)(data+2);	*(char *) (entry->validBytes + lineoffset+0) = 1;	*(char *) (entry->validBytes + lineoffset+1) = 1;	*(char *) (entry->validBytes + lineoffset+2) = 1;	break;   case 4:	if ((lineoffset & 0x03) != 0) return;	*(uint  *) (entry->data + lineoffset) = *(unsigned int *)data;	*(uint  *) (entry->validBytes + lineoffset) =  0x01010101;	break;   case 8:	if ((lineoffset & 0x07) != 0) return;	*(uint64  *) (entry->data + lineoffset) =		*(uint64 *) data;	*(uint64  *) (entry->validBytes + lineoffset) =	 ((uint64)0x01010101<<32)| (uint64 )0x01010101;	break;   default:	fprintf(stderr, "Memory op invalid size\r\n");	break;   }   return;}	/*	 *  ldst_buffer_updateRead  -  Read data from the given entry to the	 *	the data area pointed to, if it hit in the store buffer.	 *	 *	Returns 1 when the read is satisfied from the store buffer	 *	Otherwise returns 0.	 *	 *	If invalid arguments are passed, it is due to a speculative	 *	load.  This is OK, just return silently.	 *	 *	JEB: As a later enhancement, could use this as a hint to stop	 *	fetching along this thread, and activate a different one.	 */static intldst_buffer_updateRead(struct s_cpu_state *st, struct s_ldst_buffer *entry,			int paddr, char *data, int size){   int lineoffset, i;   char vb[8];   struct s_ldst_buffer *store_entry;   if (entry->loadhit == NULL) return (0);   vb[0] = vb[1] = vb[2] = vb[3] = vb[4] = vb[5] = vb[6] = vb[7] = 0;   lineoffset = paddr & 7;   if ((size+lineoffset) > 8) size = 8 - lineoffset;				/* Update this entry from the store	*/   store_entry = entry->loadhit;   for (i = 0; i < size; i++) {    if (*(char *) (store_entry->validBytes + lineoffset+i) == 1) {      data[i] =  *(char *) (store_entry->data + lineoffset+i);      vb[i+lineoffset] = 1;      }   }   for (i = 0; i < size; i++) {	lineoffset = paddr & 7;	if (vb[i+lineoffset] == 0) {	    /* Didn't update it. */	    return 0;	}   }   return 1;}	/*	 *  ldst_retire_stores  -  Retire unspeculative stores (for imprecise	 *		CPU model)	 */static void ldst_retire_stores (struct s_cpu_state *st)	{	struct	s_ldst_buffer *entry, *next_entry;	struct	s_lsq	*ls;	int	inum, ret;	INST	*ip;        next_entry = 0; /* Slience bogus compiler error message */	for (entry = st->ldst_head; (entry); entry = next_entry)		{		next_entry = entry->next;		ls = entry->ls;		if (IsLoad (ls->lstype) || IsPrefetch(ls->lstype)) continue;		if ((ls->status & LS_ST_DONE) == 0) continue;		inum = ls->inum;		ip = &st->iwin[inum];			/* Uncached loads don't need any more		*/			/* processing, just release the entry.		*/		if (ls->status & LS_ST_UNCACHED)			{			if (st->iwin_flags[inum] & IWIN_LDSTBUF)				{				st->iwin_flags [inum] &= ~IWIN_LDSTBUF;				ldst_buffer_free (st, entry);				}#ifdef DEBUG_CHECKS			if (st->iwin_flags[inum] & IWIN_SQUASH)				{				fprintf (stderr,					"Executing squashed load/store\r\n");				ms_break (st, NULL, "ERR");				}#endif /* DEBUG_CHECKS */			if (ip->r1 > 0)				reg_writeback ((void *)st, (void *)ip->r1);			else				free_inst (st, inum);			continue;			}		if ((st->iwin_flags[inum] & (IWIN_STORE | IWIN_SPEC)) ==								IWIN_STORE)			{			/* Found a store that is no longer speculative,	*/			/* so process it.				*/#ifdef DEBUG_CHECKS			if (st->iwin_flags[inum] & IWIN_SQUASH)				{				fprintf (stderr,					"Executing squashed load/store\r\n");				ms_break (st, NULL, "ERR");				}#endif /* DEBUG_CHECKS */			ret = ldst_buffer_retire (st, inum);			if (ret < 0)					/* Retry the store if the	*/					/* line has been evicted.	*/				ls->status &= ~(LS_ST_CACHED | LS_ST_DONE);			else if (ret == 0)				{	/* It worked, can free this	*/					/* instruction.			*/				if (ip->r1 > 0)					reg_writeback ((void *)st,							(void *)ip->r1);				else					free_inst (st, inum);				}			else				;	/* Still waiting for the line	*/					/* to come in, try again next	*/					/* cycle.			*/			}		}	}	/*	 *  ldst_buffer_retire  -  Do actual writes to cache as stores	 *		graduate.	 *	 *	Returns 0 if successful	 *	Returns 1 if the line hasn't come into the cache yet	 *	Returns -1 if the line has been evicted (=> need to retry)	 */int ldst_buffer_retire(struct s_cpu_state *st, int inum){	struct s_ldst_buffer *entry = st->inum2ldst[inum];#ifdef DEBUG_CHECKS	if (st->iwin_flags[inum] & IWIN_SQUASH)		{		fprintf (stderr, "Executing squashed load/store\r\n");		ms_break (st, NULL, "ERR");		}#endif /* DEBUG_CHECKS */   if (entry->ls->inum != inum) {	fprintf(stderr, "retire failure in ldst_buffer_retire\r\n");	ms_break (st, NULL, "ERR");   }   if (entry->ls->status & LS_ST_UNCACHED) goto retire_exit;   if (IsPrefetch(entry->ls->lstype)) goto retire_exit;   if (entry->invalidated) {     /* Line was nuked from the cache */	char *dataPtr;	int ret;	if (IsLoad(entry->ls->lstype) || (entry->ls->lstype == ST_INTEGER_SC)) {	    IncStat(ST_LDST_INVALIDLOAD);	    return -1;  /* Fail loads or SCs */	}	/* Refetch line for stores. */	if (entry->dataPtr == NULL) {	    IncStat(ST_LDST_WAIT);	    /* Outstanding memory op - must wait for it to finish */	    return 1;	}	st->ms_action = ACT_DCACHE_MISS;	/* Update Mipsy PC so memstat knows where miss came from. */	((CPUState *) (st->mipsyPtr))->PC = st->iwin_pc[entry->ls->inum];	ret = DCacheFetchExclusive(CPUNUM(st), entry->ls->addr,				entry->ls->paddr,0, &dataPtr);	switch (ret) {	case SUCCESS:	    entry->dataPtr = dataPtr; /* Still in cache */	    IncStat(ST_LDST_REFETCH);	    break;	case FAILURE:            /* If we got invalidated then most likley we are not in the             * second level cache.  Make this report as second level Dcache             * miss.              */            entry->cacheStallReason = E_L2 | E_D; 	    /* Cache couldn't accept the request */	    IncStat(ST_LDST_WAIT);	    return 1;  /* Retry latter. */	case STALL:	    /* Memory system has it down */	    entry->missTag = (void *) dataPtr;            entry->cacheStallReason = MxsClassifyMiss(CPUNUM(st),                                      entry->ls->addr, entry->ls->paddr, FALSE);	    entry->dataPtr = NULL;	    entry->invalidated = 0;	    IncStat(ST_LDST_REFETCH);	    return 1;	}   }   if ((entry->dataPtr == NULL) &&	/* Data not here yet. */	(entry->ls->lstype != ST_INTEGER_SC)) { /* OK for failed SCs */	  IncStat(ST_LDST_WAIT);	  return 1;   }   if (IsStore(entry->ls->lstype)) {	int off = (entry->paddr&7);	char *dst = (char *)((uint)entry->dataPtr&~7) + off;	char *src = entry->data + off;	IncStat(ST_LDST_RETIRE_STORE);#ifdef TRACE	if (tracefile)		{		struct	s_trace	trc;		trc.addr = entry->ls->addr;		trc.lstype = entry->ls->lstype;		trc.u.dreg = 0.0;		bcopy (src, (char *)&trc.u.dreg, entry->size);		fwrite (&trc, sizeof (struct s_trace), 1, tracefile);		fflush (tracefile);		}#endif	switch (entry->size) {	case 0:	   break;	case 1:	  dst[0] = src[0]; break;	case 2:	  dst[0] = src[0]; dst[1] = src[1]; break;	case 3:	  dst[0] = src[0]; dst[1] = src[1];  dst[2] = src[2]; break;	case 4:	  ((int *)dst)[0] = ((int *)src)[0]; break;	case 8:	  ((double *)dst)[0] = ((double *)src)[0]; break;	default:	   bcopy(src,dst, entry->size);	}   } else	{	IncStat(ST_LDST_RETIRE_LOAD);#ifdef TRACE	if (tracefile)		{		struct	s_trace	trc;		trc.addr = entry->ls->addr;		trc.lstype = entry->ls->lstype;		trc.u.dreg = 0.0;		trc.u.ireg = entry->ls->reg;		if (!trace_writes)			{			fwrite (&trc, sizeof (struct s_trace), 1, tracefile);			fflush (tracefile);			}		}#endif	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -