Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / tracemod / tm_cpu_ext.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: tm_cpu_ext.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
/*
* Copyright (C) 1991, 2001 Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "@(#)1.4 01/11/06 tm_blaze_ext.cc"
/*
* Copyright (c) 1989, Sun Microsystems, Inc. All Rights Reserved. Sun
* considers its source code as an unpublished, proprietary trade secret, and
* it is available only under strict license provisions. This copyright
* notice is placed here only to protect Sun in the event the source is
* deemed a published work. Disassembly, decompilation, or other means of
* reducing the object code to human readable form is prohibited by the
* license agreement under which this code is provided to the user or company
* in possession of this copy
*
* RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the
* Government is subject to restrictions as set forth in subparagraph
* (c) (1) (ii) of the Rights in Technical Data and Computer Software clause
* at DFARS 52.227-7013 and in similar clauses in the FAR and NASA FAR
* Supplement
*/
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <synch.h>
#include <dlfcn.h>
#include "types.h"
#include "blaze_globals.h"
#include "cpu_interface.h"
#include "system.h"
typedef void* TM_OPAQUE_DATA;
#include "tracemod.h"
#include "mmi.h"
#include "ui.h"
#include "tm_impl.h"
static tracemod_t *pTm_ASI_ext = NULL;
// say there are 1024 possible asi's (including room for future growth).
// we declare an array of modules, indexed by the ASI, for quick access
static const int N_ASI = 1024;
static tracemod_t *asi_modules [N_ASI];
static int asi_modules_cnt = 0;
static tracemod_t * asi2module[N_ASI] = {0};
static mmi_ld_asi_action asi2ldhandler[N_ASI] = {0};
static mmi_st_asi_action asi2sthandler[N_ASI] = {0};
/////////////////////////////////////////////////////////////
bool_t add_asi_module (tracemod_t* mod, uint32_t asi, mmi_ld_asi_action ld_handler, mmi_st_asi_action st_handler)
{
if (asi2module[asi] != NULL) {
if (mod != asi2module[asi]) {
ui->error("loading asi module %s: a module (%s) for asi %d is already loaded\n",
mod->name, asi2module[asi]->name, asi);
return FALSE;
} else {
return TRUE;
}
}
int ii = 0;
for (ii = 0; ii < asi_modules_cnt; ii++) {
if (asi_modules[ii] == mod) {
// module is already loaded, but for some other ASI
break;
}
}
if (ii == asi_modules_cnt) {
// new module
if (asi_modules_cnt >= N_ASI) {
ui->error("loading asi module %s: too many ASI modules (%d) already loaded\n",
mod->name, N_ASI);
return FALSE;
}
asi_modules[asi_modules_cnt++] = mod;
}
asi2module[asi] = mod;
asi2ldhandler[asi] = ld_handler;
asi2sthandler[asi] = st_handler;
return TRUE;
}
/////////////////////////////////////////////////////////////
// TODO : to make it more accurate
//
// ASI handling :
// Assume we have CPU (CPUM) and DEVICE module (DEVM) responsible for some extra ASI handling.
// 1. DEVM registers ASI handler with "mmi_register_asi...." with BLAZE
// 2. RS2BLAZE "glue code" registers it's own ASI callback with CPUM
// 3. When CPUM executes say LD with unsopported ASI it INVOKES callback (see #2)
// 4. This callback in turn invokes TM_execute_load/store_asi (see below).
//
int
TM_execute_load_asi (uint32_t asi, uint64_t vaddr, uint64_t *buf, int size, uint32_t cpuid)
{
tracemod_t * mod = asi2module[asi];
if (mod == NULL) return -1;
mmi_ld_asi_action ld_handler = asi2ldhandler[asi];
if (ld_handler == NULL) {
return -1;
}
return ld_handler(TM_get_asi_client_data((void*)mod), asi, vaddr, buf, size, cpuid);
}
/////////////////////////////////////////////////////////////
int
TM_execute_store_asi (uint32_t asi, uint64_t vaddr, uint64_t *buf, int size, uint32_t cpuid)
{
tracemod_t * mod = asi2module[asi];
if (mod == NULL) return -1;
mmi_st_asi_action st_handler = asi2sthandler[asi];
if (st_handler == NULL) {
return -1;
}
return st_handler(TM_get_asi_client_data((void*)mod), asi, vaddr, *buf, size, cpuid);
}