Code Search for Developers
 
 
  

simplememory_sc.h from GreenSocs at Krugle


Show simplememory_sc.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/splitcomplete.h"
#include "gstlm/userAPI/basicPorts.h"
#include "gstlm/gstlm/tlm_slave_if.h"

using namespace tlm;
using namespace SplitComplete;


#include <iomanip>

#define DELAY(x) 10*x, SC_NS

class simplememory_sc 
: public sc_module, 
  public tlm_b_if<GenericTransaction_P>,
  public tlm_slave_if<MAddr>
{
public:
  SplitCompleteTargetPort target_port;
  typedef SplitCompleteTargetPort::accessHandle accessHandle;
  typedef SplitCompleteTargetPort::phaseHandle phaseHandle;
  
  unsigned char MEM[MEMSIZE];

  std::list<std::pair<accessHandle, phaseHandle > > waiting;
  bool inWrite;
  int m_delay;

  MAddr m_base, m_high;

  // simplememory_sc functions 
  void react();
  void PVTProcess(GenericTargetPort::accessHandle,  GenericTargetPort::phaseHandle);  
  int IPmodel( GenericTargetPort::accessHandle t);

  // tlm_b_if implementation
  void b_transact(GenericTransaction_P);

  // tlm_slave_if implementation
  virtual void setAddress(MAddr  base, MAddr  high);
  virtual void getAddress(MAddr& base, MAddr& high);

    
  SC_HAS_PROCESS(simplememory_sc);

  /**
   * Constructor. 
   * @param name_ Module name.
   * @param delay_ Access delay in cycles.
   */
  simplememory_sc(sc_module_name name_, int delay_) :
    sc_module(name_),
    target_port("tport"),
    inWrite(false),
    m_delay(delay_),
    m_base(0),
    m_high(0)
  {
    target_port.bind_b_if(*this);
    
    SC_METHOD(react);
    sensitive << target_port.default_event();
    dont_initialize();
  }
};


void simplememory_sc::b_transact( GenericTransaction_P t)
{
  (void) IPmodel(t); // we dont care about timing
}


void simplememory_sc::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_sc::PVTProcess(  GenericTargetPort::accessHandle tah,  GenericTargetPort::phaseHandle p)
{
  
  switch (p.state) {
    
  case GenericPhase::RequestValid:
    {
      if (inWrite) {
        //keep writes in order !!!
        GSTRACE("I am busy... can't process this write for now");
        waiting.push_back(std::pair<GenericTargetPort::accessHandle,  GenericTargetPort::phaseHandle > (tah,p));

        target_port.Split(tah,p);
      } 
      else {
        target_port.AckRequest(tah, p, DELAY(1));
        
        if (tah->get_mCmd() == Generic_MCMD_RD) {
          GSTRACE("accepted READ cmd, sending data now.");
          target_port.Response(tah, p, DELAY(IPmodel(tah)));
        } else {
          GSTRACE("accepted WRITE cmd (in 1 cycle), now waiting for data.");
          inWrite=true;
        }
      }
    }
    break;
    
    
  case GenericPhase::DataAccepted:
    {
      GSTRACE("master sent DataAccepted. Transaction finished OK.");
    }
    break;
    
    
  case GenericPhase::DataValid:
    {
      GSTRACE("receiving data from master.");
      MasterDataType my_data;
      my_data.set(tah->get_mData());
      
      // dump data to screen
      cout<<name()<<" @ "<<sc_time_stamp()<<"/"<<sc_delta_count()
          <<": got data [size="<<my_data.byte_size()<<"] {";
      for (unsigned int i=0; i<my_data.byte_size(); i++) {
        cout<<my_data[i]<<flush;
      }
      cout<<"}"<<endl;

      tah->get_mData(MasterDataType( & MEM[tah->get_mAddr()-m_base] ,tah->get_mBurstLength() ));      

      // send DataAck
      target_port.AckData(tah,p,DELAY(tah->get_mBurstLength()-1));
      
      inWrite =false;
      if (!waiting.empty()) {
        GSTRACE(" RE-AWAKE pending write  ");
        std::pair<GenericTargetPort::accessHandle,  GenericTargetPort::phaseHandle > 
          pair =waiting.front();
        waiting.pop_front();

        target_port.Complete(pair.first,pair.second);

        PVTProcess(pair.first,pair.second);
      }
    }
    break;
    
  case GenericPhase::ResponseAccepted:
    {
      GSTRACE("master sent ResponseAccepted. Transaction finished OK.");
    }
    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_sc::IPmodel( GenericTargetPort::accessHandle t)
{
  switch (t->get_mCmd()) {

  case Generic_MCMD_RD:
    GSTRACE("processing blocking READ");
    cout<<"BurstL: "<<t->get_mBurstLength()<<endl
        <<"Addr: "<<(t->get_mAddr()-m_base)<<endl
        <<"Data: "<<(MEM[t->get_mAddr()-m_base])<<endl
        <<flush;
    t->set_sData(MasterDataType( & MEM[t->get_mAddr()-m_base] ,t->get_mBurstLength() ));
    return m_delay;
    break;

  case Generic_MCMD_WR:
    GSTRACE("processing blocking WRITE");
    t->get_mData(MasterDataType( & MEM[t->get_mAddr()-m_base] ,t->get_mBurstLength() ));
    return m_delay*2;
    break;
  }

  return 0;

}



void simplememory_sc:: setAddress(MAddr  base, MAddr  high) 
{
  m_base =base;
  m_high =high;
}

void simplememory_sc:: getAddress(MAddr& base, MAddr& high)
{
  base =m_base;
  high =m_high;
}





See more files for this project here

GreenSocs

To develop SystemC infrustructure, basic IP, patches and add on library code for eventual standerdization.\r\nThe GreenSocs project is made up of a number of contributions (sub projects). Please visit www.greensocs.com for more information.

Project homepage: http://sourceforge.net/projects/greensocs
Programming language(s): C,C++,Java,Perl,XML
License: other

  Makefile
  example_splitcomplete.cpp
  sillysort.h
  simplemaster.h
  simplememory_sc.h