Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / tracemod / tm_blaze_ext.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: tm_blaze_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 <alloca.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 "system.h"
typedef void* TM_OPAQUE_DATA;
#include "tracemod.h"
#include "ui.h"
#include "tm_impl.h"
//////////////////////////////////////////////////////////
void *TM_get_blaze_data (void * handle)
{
return ((Ldm*)handle)->blaze_data;
}
//////////////////////////////////////////////////////////
void *TM_get_client_data (void * handle)
{
Ldm *pldm = (Ldm*)handle;
return pldm->client_data;
}
//////////////////////////////////////////////////////////
void *TM_get_asi_client_data (void * handle)
{
Ldm *pldm = (Ldm*)handle;
return pldm->asi_client_data;
}
//////////////////////////////////////////////////////////
char *TM_get_name (void * handle)
{
Ldm *pldm = (Ldm*)handle;
return pldm->name;
}
//////////////////////////////////////////////////////////
bool_t TM_is_device ()
{
LdmNode * pnode;
for (pnode=head_ldm; pnode!=NULL; pnode=pnode->Next()) {
Ldm *pldm = pnode->GetData();
if (pldm->type == TM_TYPE_EXT_DEVICE) {
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////
tracemod_t *TM_get_mod (void * handle)
{
LdmNode *pnode = (LdmNode*) handle;
return pnode->GetData ();
}
//////////////////////////////////////////////////////////
void *TM_getnext_ext (void * handle, uint32_t mode)
{
LdmNode *pnode = (LdmNode*)handle;
Ldm *pldm;
if (pnode == NULL) {
pnode = (LdmNode*)head_spec_ldm;
}
else {
pnode = pnode->Next();
}
for (;pnode;pnode = pnode->Next()) {
pldm = pnode->GetData ();
if (pldm->mode & mode) {
return pnode;
}
}
return NULL;
}
//////////////////////////////////////////////////////////
// Internal API routine :
// Is used to bind a MODULE with specific opaque data
// consealed inside of other BLAZE subsystem (SCHIZO for instance)
//
void TM_include_ext (void * io_module, void *local_handle)
{
Ldm *pldm = (Ldm*)io_module;
pldm->blaze_data = local_handle;
if (pldm->mode & TM_EXT_IO) {
if ((pldm->io_ld_action == NULL) && (pldm->io_mmi_ld_action == NULL)) {
ui->error("extension <%s> doesn't have LOAD op handler\n", pldm->name);
}
if ((pldm->io_st_action == NULL) && (pldm->io_mmi_st_action == NULL)) {
ui->error("extension <%s> doesn't have STORE op handler\n", pldm->name);
}
}
}
//////////////////////////////////////////////////////////
fn_misc TM_get_ld_action_ext (void *io_module)
{
Ldm *pldm = (Ldm*)io_module;
return pldm->io_ld_action;
}
//////////////////////////////////////////////////////////
fn_misc TM_get_st_action_ext (void *io_module)
{
Ldm *pldm = (Ldm*)io_module;
return pldm->io_st_action;
}
//////////////////////////////////////////////////////////
uint32_t TM_is_ready_ext (void * /* io_module */)
{
return 1; // always ready
}
//////////////////////////////////////////////////////////
fn_misc TM_get_st_mmi_action_ext (void *io_module)
{
Ldm *pldm = (Ldm*)io_module;
return pldm->io_mmi_st_action;
}
//////////////////////////////////////////////////////////
fn_misc TM_get_ld_mmi_action_ext (void *io_module)
{
Ldm *pldm = (Ldm*)io_module;
return pldm->io_mmi_ld_action;
}
//////////////////////////////////////////////////////////
// EXTERNAL
// ---------
// This routine registers module object
// without existing *.so file.
// Another words an entire NAME RELATED functionality
// can be bound with this PSEUDOMODULE
//
tracemod_t *TM_self_pseudomod_spec (tracemod_t *main_mod, const char* mod_name,
const char *help, TM_OPAQUE_DATA client_data)
{
Ldm *pldm = NULL;
if (SYSTEM_is_running()) {
ui->fatal("TM_self_pseudomod_spec called while blaze running\n");
exit (1);
}
pldm = ldm_add_spec ((char*)mod_name, NULL);
if (pldm == NULL) {
return NULL;
}
pldm->argc = 1;
pldm->argv = (char**) calloc (1, sizeof(char*));
pldm->argv[0] = strdup(mod_name);
pldm->so_handle = 0;
pldm->valid = TRUE;
pldm->help = strdup(help);
pldm->client_data = client_data;
pldm->parent = main_mod;
return pldm;
}
//////////////////////////////////////////////////////////
// EXTERNAL
// --------
void TM_register_io_action (tracemod_t *mod, fn_misc ld_action, fn_misc st_action)
{
mod->io_ld_action = ld_action;
mod->io_st_action = st_action;
}
//////////////////////////////////////////////////////////
void TM_register_io_mmi_action (tracemod_t *mod, fn_misc ld_action, fn_misc st_action)
{
mod->io_mmi_ld_action = ld_action;
mod->io_mmi_st_action = st_action;
}
//////////////////////////////////////////////////////////
void TM_register_client_data (tracemod_t *mod, TM_OPAQUE_DATA d)
{
mod->client_data = d;
}
void TM_register_asi_client_data (tracemod_t *mod, TM_OPAQUE_DATA d)
{
mod->asi_client_data = d;
}
//////////////////////////////////////////////////////////
// time_intf
//////////////////////////////////////////////////////////
mutex_t time_intf_lock;
ldm_time_intf *head_time_intf;
void ldm_tick_ext_init()
{
mutex_init(&time_intf_lock, USYNC_THREAD, NULL);
}
//////////////////////////////////////////////////////////
void TM_enable_time_intf (void *intf, uint64_t how_often)
{
ldm_time_intf *time_intf = (ldm_time_intf*)intf;
time_intf->threshold = how_often;
time_intf->cnt = how_often;
time_intf->status = TM_INTF_STATUS_ENABLED;
}
//////////////////////////////////////////////////////////
void TM_disable_time_intf (void *intf)
{
ldm_time_intf *time_intf = (ldm_time_intf*)intf;
time_intf->status = TM_INTF_STATUS_DISABLED;
}
//////////////////////////////////////////////////////////
void *TM_register_time_intf (tracemod_t *mod, TM_OPAQUE_DATA d, fn_event_cycle handler, uint64_t how_often)
{
ldm_time_intf *time_intf = (ldm_time_intf*)calloc (1, sizeof(ldm_time_intf));
assert(time_intf);
time_intf->threshold = how_often;
time_intf->cnt = how_often;
time_intf->event_handler = handler;
time_intf->client_data = d;
time_intf->self = time_intf;
time_intf->owner = mod;
time_intf->status = TM_INTF_STATUS_ENABLED;
mutex_lock(&time_intf_lock);
time_intf->next = head_time_intf;
head_time_intf = time_intf;
mutex_unlock(&time_intf_lock);
return time_intf;
}
//////////////////////////////////////////////////////////
void TM_unregister_time_intf (tracemod_t *mod, void *intf)
{
ldm_time_intf *time_intf, **prev;
mutex_lock(&time_intf_lock);
for (prev = &head_time_intf; (time_intf = *prev) != NULL; ) {
if (!intf && time_intf->owner == mod) {
*prev = time_intf->next;
free ((void*)time_intf);
}
else if (time_intf == intf) {
*prev = time_intf->next;
free ((void*)time_intf);
break;
}
else
prev = &time_intf->next;
}
mutex_unlock(&time_intf_lock);
}
//////////////////////////////////////////////////////////
void TM_tick_ext (int incr)
{
ldm_time_intf *copy;
ldm_time_intf *time_intf;
ldm_time_intf *time_intf_copy = NULL;
// make a copy of callbacks while the lock is held
mutex_lock(&time_intf_lock);
for (time_intf = head_time_intf; time_intf; time_intf = time_intf->next) {
if (time_intf->status == TM_INTF_STATUS_ENABLED) {
time_intf->abs_cnt += incr;
if ((time_intf->cnt -= incr) <= 0) {
// the owner is always ready to accept the tick callback
copy = (ldm_time_intf *) alloca(sizeof(ldm_time_intf));
assert(copy);
*copy = *time_intf;
copy->next = time_intf_copy;
time_intf_copy = copy;
time_intf->cnt = time_intf->threshold;
}
}
}
mutex_unlock(&time_intf_lock);
// now call the handlers without a lock
while ((time_intf = time_intf_copy) != NULL) {
time_intf_copy = time_intf->next;
time_intf->event_handler(time_intf->client_data, time_intf->abs_cnt);
}
}