Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / sam / src / SS_VirtualCpu.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: SS_VirtualCpu.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 ============================================
#include "SS_VirtualCpu.h"
uint_t SS_VirtualCpu::id = 0;
SS_VirtualCpu* SS_VirtualCpu::list = 0;
SS_VirtualCpu::SS_VirtualCpu( SS_Model* model )/*{{{*/
:
next(0),
cpu(model->cpu[id]),
strand(new SS_VirtualStrand[cpu->strand_cnt()])
{
cpu->clr_stepping();
// The virtual cpu id (vid) numbers from 0 to N-1.
// The strand id associated with vid X is sid X
// if the id is not overwritten in the rc file.
for (int s=0; s < cpu->strand_cnt(); s++)
strand[s].strand = cpu->strand[s];
++id;
}
/*}}}*/
SS_VirtualStrand* SS_VirtualCpu::create( SS_Model* (*model)(), Sam::VCPU_Config* config, Sam::VCPU_ImpIntf* interface )/*{{{*/
{
SS_VirtualCpu* pntr;
uint_t base_id = 0;
// Get the strand with strand_id() number config->id .
// Whilst locating the strand create any missing cpu instances.
if (list == 0)
{
SS_Model* ss = (model)();
ss->create_cpu(1);
list = new SS_VirtualCpu(ss);
}
for (pntr = list; config->id >= (pntr->cpu->strand_cnt() + base_id) ; pntr = pntr->next)
{
base_id += pntr->cpu->strand_cnt();
if (pntr->next == 0)
{
SS_Model* ss = (model)();
ss->create_cpu(1);
pntr->next = new SS_VirtualCpu(ss);
}
}
uint_t i = config->id - base_id;
// Connect the strand to the "outside" world
pntr->strand[i].strand->io->set_access_io(interface->access_io);
pntr->strand[i].strand->memory = interface->mem;
pntr->strand[i].strand->asi_ext_obj = &pntr->strand[i];
pntr->strand[i].strand->asi_ext_ld64_fp = ss_asi_ext_ld64;
pntr->strand[i].strand->asi_ext_st64_fp = ss_asi_ext_st64;
pntr->strand[i].config = *config;
pntr->strand[i].sys_intf = *interface;
// Make the strand active in step().
pntr->cpu->set_stepping(i);
// Return the virtual cpu instance.
return &pntr->strand[i];
}
/*}}}*/
void SS_VirtualCpu::remove( SS_Model* ss )/*{{{*/
{
while (list)
{
SS_VirtualCpu* hlp = list;
list = list->next;
delete hlp;
}
delete ss;
}
/*}}}*/
int SS_VirtualCpu::snapshot( SS_Model* model, const char* dir_name, const char* file_name, bool load )/*{{{*/
{
char name[1024];
name[0] = 0;
if (dir_name)
strcat(name,dir_name);
strcat(name,file_name);
FILE* file = fopen(name,load ? "r" : "w");
if (file == 0)
return -1;
SS_SnapShot ss(file,load);
model->snapshot(ss);
if (fclose(file) == 0)
return -1;
return 0;
}
/*}}}*/
int SS_VirtualCpu::cycle( uint64_t nn )
{
assert(nn==1);
SS_VirtualStrand *vcpu = SS_VirtualCpu::list ? SS_VirtualCpu::list->strand : NULL;
if ( vcpu && vcpu->config.trace_on && vcpu->config.execution_driven )
{
vcpu->sys_intf.vtrace->cycle();
}
return 0;
}
SS_AsiSpace::Error SS_VirtualCpu::ss_asi_ext_ld64( SS_Node*, void* asi_ptr, SS_Strand* s, SS_Vaddr va, uint64_t* data )/*{{{*/
{
int sid = s->strand_id();
uint8_t asi = *((uint8_t *)asi_ptr);
SS_VirtualStrand *v = (SS_VirtualStrand *)s->asi_ext_obj;
int ok = v->sys_intf.access_asi(sid, Sam::VCPU_LOAD_OP, asi, va, 8, (*data));
return SS_AsiSpace::Error(ok);
}
/*}}}*/
SS_AsiSpace::Error SS_VirtualCpu::ss_asi_ext_st64( SS_Node*, void* asi_ptr, SS_Strand* s, SS_Vaddr va, uint64_t data )/*{{{*/
{
int sid = s->strand_id();
uint8_t asi = *((uint8_t *)asi_ptr);
SS_VirtualStrand *v = (SS_VirtualStrand *)s->asi_ext_obj;
int ok = v->sys_intf.access_asi(sid, Sam::VCPU_STORE_OP, asi, va, 8, data);
return SS_AsiSpace::Error(ok);
}
/*}}}*/