📄 ubuf.c
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and * William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: * Professor Sarita Adve's RSIM research group * University of Illinois at Urbana-Champaign and William Marsh Rice University * http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: * The Impulse Research Group, University of Utah * http://www.cs.utah.edu/impulse * Lambert Schaelicke, University of Utah and University of Notre Dame du Lac * http://www.cse.nd.edu/~lambert * Mike Parker, University of Utah * http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimers. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimers in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, * the University of Illinois at Urbana-Champaign, William Marsh Rice * University, nor the names of its contributors may be used to endorse * or promote products derived from this Software without specific prior * written permission. * 4. Neither the names of the ML-RSIM project, the URSIM project, the * Impulse research group, the University of Utah, the University of * Notre Dame du Lac, nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE. */#include <stdlib.h>#include <string.h>#include "Processor/simio.h"#include "Processor/tlb.h"#include "Processor/memunit.h"#include "sim_main/simsys.h"#include "sim_main/stat.h"#include "Caches/req.h"#include "Caches/cache.h"#include "Caches/ubuf.h"#include "IO/io_generic.h"UBUF **UBuffers;int MaxCoalesce (UBUF*, int);/*#define UBUF_TRACE *//*===========================================================================*//* Add a request to the uncached buffer. Called by cached module. *//* Returns 1 if request was consumed, 0 if not. Removes request from *//* caches incoming request queue (above->request_queue) upon success, and *//* frees the request structure if appropriate. *//*===========================================================================*/int UBuffer_add_request(REQ *req){ UBUF *ubufptr = PID2UBUF(req->node, req->src_proc); int top, n;#ifdef UBUF_TRACE YS__logmsg(req->node, "### %i %s Request at Uncached Buffer 0x%08X (%i) %.0f\n", req->type, ReqName[req->prcr_req_type], req->paddr, req->size, YS__Simtime);#endif /*=========================================================================*/ /* memory barrier: mark in latest buffer entry if present */ /*=========================================================================*/ if (req->type == BARRIER) { if (ubufptr->num_entries > 0) { ubufptr->entries[ubufptr->num_entries - 1]->fence = 1; ubufptr->cur_reads++; ubufptr->num_barr_eff++;#ifdef UBUF_TRACE YS__logmsg(req->node, "### Inserting Memory Barrier at Uncached Buffer %.0f\n", YS__Simtime);#endif } lqueue_remove(&(ubufptr->above->request_queue)); YS__PoolReturnObj(&YS__ReqPool, req); ubufptr->num_barriers++; return(1); } /*=========================================================================*/ /* access to combining address space */ /*=========================================================================*/ if ((req->type == REQUEST) && (req->prcr_req_type == RMW)) YS__errmsg(req->node, "RMW Request not supported by uncached buffer\n"); /*=========================================================================*/ /* non-accelerated requests */ /*=========================================================================*/ top = ubufptr->num_entries; if ((ubufptr->combine) && (ubufptr->num_entries > 0) && ((req->size == WD) || (req->size == DW))) { for (n = ubufptr->num_entries-1; n >= 0; n--) { if ((ubufptr->entries[n]->type != req->prcr_req_type) || (ubufptr->entries[n]->fence) || (ubufptr->entries[n]->busy)) break; if (ubufptr->entries[n]->address == (req->paddr & ubufptr->line_mask)) { top = n; break; } } } /* buffer full and combining failed - abort -------------------------------*/ if ((top == ubufptr->num_entries) && (ubufptr->num_entries >= ubufptr->size)) { ubufptr->stall_ub_full++; return(0); } /* allocate new entry if cannot (or may not) combine ----------------------*/ if (top == ubufptr->num_entries) { memset(ubufptr->entries[top]->reqs, 0, ubufptr->entrysz * sizeof(REQ*)); ubufptr->num_entries++; } #ifdef UBUF_TRACE else YS__logmsg(req->node, "### Combining %x with %x in %i\n", ubufptr->entries[top]->address, req->paddr, top);#endif /* insert entry into corresponding bucket ---------------------------------*/ req->hit_type = IOHIT; /* overwriting existing entry: mark as done (without perform) and free ----*/ if (ubufptr->entries[top]->reqs[(unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz)] != NULL) { MemDoneHeapInsertSpec(ubufptr->entries[top]-> reqs[(unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz)], IOHIT); ReturnMemopSpec(ubufptr->entries[top]-> reqs[(unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz)]); YS__PoolReturnObj(&YS__ReqPool, ubufptr->entries[top]-> reqs[(unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz)]); } ubufptr->entries[top]-> reqs[(unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz)] = req; ubufptr->entries[top]->fence = 0; ubufptr->entries[top]->address = req->paddr & ubufptr->line_mask; ubufptr->entries[top]->type = req->prcr_req_type; ubufptr->entries[top]->busy = 0; if (req->prcr_req_type == READ) /* change request type */ { req->req_type = READ_UC; /* to `uncached' */ ubufptr->cur_reads++; } else req->req_type = WRITE_UC; #ifdef UBUF_TRACE YS__logmsg(req->node, "### Inserting %s (%x) into slot %i.%i\n", ReqName[ubufptr->entries[top]->type], req->paddr, top, (unsigned)(req->paddr / 4) % (unsigned)(ubufptr->entrysz));#endif lqueue_remove(&(ubufptr->above->request_queue)); FreeAMemUnit(req->d.proc_data.proc_id, req->d.proc_data.inst_tag); req->progress = 0; StatrecUpdate(ubufptr->occ, ubufptr->num_entries, (long long)YS__Simtime); return(1);} /*===========================================================================*//* Try to send a request to the bus interface. Called by main simulator *//* routine if regular uncached buffer is not empty, or CSB has a complete *//* request. Set flag 'transaction_pending' if something has been send to *//* the bus interface (below->..), the flag will be cleared by the bus *//* interface when the transaction is ready to issue (next in queue, *//* starts driving bus, completed on bus ..., depending on policy) *//*===========================================================================*/void UBuffer_out_sim(int gid){ REQ *req, *nreq, *creq; UBUF *ubufptr = UBuffers[gid]; int n, i, j, num_coals, size; int max_wr_coals, max_rd_coals; if (ubufptr->transaction_pending) return; /*=========================================================================*/ /* other uncached loads/stores */ max_wr_coals = 0; max_rd_coals = 0; if ((ubufptr->num_entries >= ubufptr->flush) || (ubufptr->cur_reads > 0)) { /*---------------------------------------------------------------------*/ /* find first request within oldest entry */ i = 0; while ((i < ubufptr->entrysz) && ((req = ubufptr->entries[0]->reqs[i]) == NULL)) i++; if (i >= ubufptr->entrysz) YS__errmsg(gid / ARCH_cpus, "Empty entry in Uncached Buffer\n"); /* check if can send down */ /*---------------------------------------------------------------------*/ /* if output port not full: possibly coalesce and send out */ num_coals = MaxCoalesce(ubufptr, i); /* get number of coals */ creq = req; ubufptr->entries[0]->reqs[i] = NULL; j = i + req->size / 4; /* skip to next request */ /* walk through request */ for (j = i + req->size / 4, n = req->size / 4; n < num_coals; /* array in size-steps */ n += size / 4, j += size / 4) { nreq = ubufptr->entries[0]->reqs[j]; /* get next request */ size = nreq->size; req->size += nreq->size; /* increment size */ creq->parent = nreq; creq = nreq; ubufptr->entries[0]->reqs[j] = NULL; /*-----------------------------------------------------------------*/ if (req->prcr_req_type == READ) { ubufptr->cur_reads--; max_rd_coals += size; ubufptr->num_rd_coals++; } else { max_wr_coals += size; ubufptr->num_wr_coals++; } } /* end for loop */ /*---------------------------------------------------------------------*/ if (req->req_type == READ_UC) ubufptr->cur_reads--; ubufptr->transaction_pending = 1; Cache_start_send_to_bus(ubufptr->below, req);#ifdef UBUF_TRACE YS__logmsg(gid / ARCH_cpus, "### Forwarding %s request %x %i %.2f --> %i\n", ReqName[req->req_type], req->paddr, req->size, YS__Simtime, ubufptr->num_entries);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -