Show simplememory.h syntax highlighted
// LICENSETEXT
//
// Copyright (C) 2005,2006 :
// GreenSocs Ltd
// (http://www.greensocs.com/),
//
// email: info@greensocs.com
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This 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 program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// ENDLICENSETEXT
#include <systemc.h>
#include <list>
using std::list;
#include "gstlm/gstlm/tlm.h"
#include "gstlm/protocol/generic.h"
#include "gstlm/userAPI/basicPorts.h"
using namespace tlm;
#include <iomanip>
#ifndef SHOW_SC_TIME
//#define SHOW_SC_TIME_(module,msg) cout << "time " << std::setw(3) << sc_simulation_time() << ": " \
// << std::setw(6) << #module << ": " << msg
//#define SHOW_SC_TIME(module,msg) SHOW_SC_TIME_(module,msg) << endl
#define SHOW_SC_TIME_(module,msg) // nothing
#define SHOW_SC_TIME(module,msg) // nothing
#endif
#define CYCLES(x) 3*x, SC_NS
class simplememory : public sc_module, public tlm_b_if<GenericTransaction_P>
{
public:
GenericTargetPort target_port;
typedef GenericTargetPort::phaseHandle phaseHandle;
unsigned char MEM[MEMSIZE];
std::list<std::pair<GenericTargetPort::accessHandle, GenericTargetPort::phaseHandle > > waiting;
bool inWrite;
void react();
void simplememory::PVTProcess( GenericTargetPort::accessHandle, GenericTargetPort::phaseHandle);
void b_transact(GenericTransaction_P);
int IPmodel( GenericTargetPort::accessHandle t);
//Constructor
SC_CTOR( simplememory ) :
target_port ("tport")
{
target_port.bind_b_if(*this);
inWrite=false;
SC_METHOD( react );
sensitive << target_port.default_event();
dont_initialize();
}
};
void simplememory::b_transact( GenericTransaction_P t)
{
(void) IPmodel(t); // we dont care about timing
}
void simplememory::react()
{
GenericTargetPort::accessHandle tah=target_port.get_transactionHandle();
GenericTargetPort::phaseHandle p=target_port.get_phase();
PVTProcess(tah,p);
}
/* This method plays out the protocol. We can do this how we like, so long as we
* stick to the generic protocol. We can hard wire in some number, ask the IP
* block, be random, whatever. These numbers determin which "real" bus protocol
* we are essencially modelling */
void simplememory::PVTProcess( GenericTargetPort::accessHandle tah, GenericTargetPort::phaseHandle p)
{
switch (p.state) {
case GenericPhase::RequestValid:
if (inWrite) {
//keep writes in order !!!
SHOW_SC_TIME(simplememory, "PVT : can't process this write for now ");
waiting.push_back(std::pair<GenericTargetPort::accessHandle, GenericTargetPort::phaseHandle > (tah,p));
} else {
target_port.FinishBlocking(tah,p,CYCLES(2) ); // great, I'm ready!
if (tah->get_mCmd() == Generic_MCMD_RD) {
SHOW_SC_TIME(simplememory, "PVT : Accepted Read (in 10) sending master data in 50");
// because we can, copy it all on beat one but
// it takes some time, get the IP model to
// tell us
target_port.SendData(tah,p,CYCLES(IPmodel(tah)));
} else {
SHOW_SC_TIME(simplememory, "PVT : Accepted write (in 10) waiting for Data ");
inWrite=true;
}
}
break;
case GenericPhase::DataAccepted:
if (p.BurstNumber >= tah->get_mBurstLength()) {
target_port.Response(tah,p,CYCLES(2));
} //
// we could have said "else" here, if the protocol we are trying to
// model sends the last item in the respose
target_port.SendData(tah,p,CYCLES(1));
break;
case GenericPhase::DataValid:
SHOW_SC_TIME(simplememory, "PVT : Got Data Ack ");
if (p.BurstNumber >= tah->get_mBurstLength()) {
SHOW_SC_TIME(simplememory, "PVT : Response send");
// it takes some time after the data has all come in for it to be
// consumed, get the IP model to tell us.
target_port.Response(tah,p,CYCLES(IPmodel(tah)));
}
target_port.AckData(tah,p,CYCLES(1));
break;
case GenericPhase::ResponseAccepted:
SHOW_SC_TIME(simplememory, "PVT : " << tah->get_mCmd());
if (tah->get_mCmd() == Generic_MCMD_WR) {
inWrite=false;
}
if (!inWrite) {
if (!waiting.empty()) {
SHOW_SC_TIME(simplememory, "PVT : RE-AWAKE pending write ");
std::pair<GenericTargetPort::accessHandle, GenericTargetPort::phaseHandle > pair= waiting.front();
waiting.pop_front();
PVTProcess(pair.first,pair.second);
}
}
// Always nice to know
break;
default:
SC_REPORT_ERROR( sc_core::SC_ID_INTERNAL_ERROR_, "Phase not recognized" );
break;
}
}
/* Here is what the user should end up writing
a very simple model,
to work in a 'co-war' like environment, where the model writer thinks about
timing up front, then this model can return a timing number, or a strucutre
of timing numbers if required */
int simplememory::IPmodel( GenericTargetPort::accessHandle t)
{
SHOW_SC_TIME_(simplememory, "blocking: cmd " << t->get_mCmd());
switch (t->get_mCmd()) {
case Generic_MCMD_RD:
// cout << " (read)\n";
t->set_sData(MasterDataType( & MEM[t->get_mAddr()] ,t->get_mBurstLength() ));
return 10;
break;
case Generic_MCMD_WR:
// cout << " (write)\n";
t->get_mData(MasterDataType( & MEM[t->get_mAddr()] ,t->get_mBurstLength() ));
return 20;
break;
}
}
See more files for this project here