Repository Access Links:

This URL has Read-Only access.
Statistics
| Branch: | Tag: | Revision:

greenlib / greenreg / include / greenreg / greenreg_socket / gr_gsgpsocket.h @ e1ff4bc1

History | View | Annotate | Download (10.5 kB)

1
//   GreenReg framework
2
//
3
// LICENSETEXT
4
//
5
//   Copyright (C) 2008-2009 : GreenSocs Ltd
6
//    http://www.greensocs.com/ , email: info@greensocs.com
7
//
8
//   Developed by :
9
//   
10
//
11
//
12
//   This program is free software.
13
// 
14
//   If you have no applicable agreement with GreenSocs Ltd, this software
15
//   is licensed to you, and you can redistribute it and/or modify
16
//   it under the terms of the GNU General Public License as published by
17
//   the Free Software Foundation; either version 2 of the License, or
18
//   (at your option) any later version.
19
// 
20
//   If you have a applicable agreement with GreenSocs Ltd, the terms of that
21
//   agreement prevail.
22
// 
23
//   This program is distributed in the hope that it will be useful,
24
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
25
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
//   GNU General Public License for more details.
27
// 
28
//   You should have received a copy of the GNU General Public License
29
//   along with this program; if not, write to the Free Software
30
//   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
31
//   02110-1301  USA 
32
// 
33
// ENDLICENSETEXT
34

    
35
#ifndef _GR_GSGPSOCKET_H_
36
#define _GR_GSGPSOCKET_H_
37

    
38
#include "greenreg/greenreg.h"
39
#include "transactor_if.h"
40

    
41
#include "gsgpsocket/transport/GSGPSlaveSocket.h"
42
#include "gsgpsocket/transport/GSGPMasterBlockingSocket.h"
43

    
44

    
45
// greensocket
46

    
47
namespace gs {
48
namespace gp {
49

    
50
  class generic_slave_base
51
  {
52
  public:
53
    generic_slave_base(gs::reg::I_register_container_bus_access * _registers,
54
                       gr_uint_t _base_addr,
55
                       gr_uint_t _decode_size )
56
    : m_registers( _registers)
57
    , m_decode_size( _decode_size)
58
    , m_base_addr( _base_addr)
59
    , m_delay_enabled(true) // enabled by default
60
    {
61
    }
62

    
63
    virtual ~generic_slave_base()
64
    {}
65

    
66
    inline gr_uint_t get_decode_size() { return m_decode_size; }
67
    
68
    /// Disables the delay for all notification rule callbacks caused by this socket
69
    void disable_delay() { m_delay_enabled = false; }
70
    /// Enables the delay for all notification rule callbacks caused by this socket
71
    void enable_delay() { m_delay_enabled = true; }
72
    /// Returns if the delay is enabled
73
    bool delay_enabled() {return m_delay_enabled; }
74
    
75
  protected:
76
    bool write_to_module( unsigned int _data, unsigned int _address, unsigned int _byte_enable, gs::reg::transaction_type* _transaction, bool _delayed) {
77
      return( m_registers->bus_write( _data, _address, _byte_enable, _transaction, _delayed));
78
    }
79

    
80
    unsigned int read_from_module( unsigned int& _data, unsigned int _address, unsigned int _byte_enable, gs::reg::transaction_type* _transaction, bool _delayed) {
81
      return( m_registers->bus_read( _data, _address, _byte_enable, _transaction, _delayed));
82
    }
83

    
84
    gs::reg::I_register_container_bus_access * m_registers;
85
    gr_uint_t m_decode_size;
86

    
87
  protected:
88
    gr_uint_t m_base_addr;
89
    
90
    /// If this socket let the caused notification rule callbacks be delayed
91
    bool m_delay_enabled;
92
    
93
  };
94

    
95
  class generic_slave 
96
  //: public sc_core::sc_module
97
  : public gs::gp::GenericSlavePort<32>
98
  , public generic_slave_base
99
  , public gs::tlm_b_if<gs::gp::GenericSlaveAccessHandle>
100
  , public gs::payload_event_queue_output_if<gs::gp::slave_atom>
101
  {
102
  public:
103

    
104
    typedef gs::gp::GenericSlavePort<32>::accessHandle accessHandle_slave;
105
    typedef gs::gp::GenericSlavePort<32>::phase phase_slave;
106
    typedef gs::gp::GenericSlavePort<32>::virtual_base_type virtual_base_type;
107

    
108
    SC_HAS_PROCESS( generic_slave);
109

    
110
    generic_slave( sc_core::sc_module_name _name, gs::reg::I_register_container_bus_access & _reg_bind, gr_uint_t _base_address, gr_uint_t _decode_size)
111
    //: sc_core::sc_module( _name)
112
    : virtual_base_type(_name/*"slave_port"*/, GSGP_SLAVE_SOCKET_TYPE_NAME)
113
    , gs::gp::GenericSlavePort<32>( _name/*"slave_port"*/)
114
    , generic_slave_base( &_reg_bind, _base_address, _decode_size)
115
    , m_base( _base_address)
116
    , m_high( _base_address + _decode_size)
117
    {
118
      gs::gp::GenericSlavePort<32>::bind_b_if( *this);
119
      gs::gp::GenericSlavePort<32>::peq.out_port(*this);
120
      
121
      gs::gp::GenericSlavePort<32>::base_addr = _base_address;
122
      gs::gp::GenericSlavePort<32>::high_addr = _base_address + _decode_size;
123
    }
124

    
125
    generic_slave( sc_core::sc_module_name _name, gs::reg::I_register_container_bus_access & _reg_bind)
126
    //: sc_core::sc_module( _name)
127
    : virtual_base_type(_name/*"slave_port"*/, GSGP_SLAVE_SOCKET_TYPE_NAME)
128
    , gs::gp::GenericSlavePort<32>( _name/*"slave_port"*/)
129
    , generic_slave_base( &_reg_bind, base_addr, high_addr - base_addr)
130
    , m_base( base_addr)
131
    , m_high( high_addr)
132
    {
133
      gs::gp::GenericSlavePort<32>::bind_b_if( *this);
134
      gs::gp::GenericSlavePort<32>::peq.out_port(*this);
135
      
136
//       gs::gp::GenericSlavePort<32>::base_addr = _base_address;
137
//       gs::gp::GenericSlavePort<32>::high_addr = _base_address + _decode_size;
138
      if (high_addr == 0) {
139
        std::stringstream ss;
140
        ss << "check parameter value for " << base_addr.getName() << "=" << base_addr << " and "
141
           << high_addr.getName() << "=" << high_addr << ". They should be initialized already.";
142
        GR_FATAL(ss.str().c_str());
143
      }
144
    }
145

    
146
    virtual ~generic_slave()
147
    {}
148

    
149
    /// this method does not care about time
150
    void b_transact(gs::gp::GenericSlaveAccessHandle _transaction) {
151
      stimulate_model( _transaction);
152
    }
153

    
154
    // tlm_slave_if implementation
155
    virtual void setAddress(sc_dt::uint64 base, sc_dt::uint64 high) {
156
      m_base =base;
157
      m_high =high;
158

    
159
      gs::gp::GenericSlavePort<32>::base_addr = base;
160
      gs::gp::GenericSlavePort<32>::high_addr = high;        
161
    }
162
    
163
    virtual void getAddress(sc_dt::uint64& base, sc_dt::uint64& high) {
164
      base =m_base;
165
      high =m_high;
166
    }
167

    
168
    void notify(gs::gp::slave_atom& tc) {
169
    }    
170
    
171
    /// this method is timing agnostic
172
    int stimulate_model(accessHandle_slave _transaction) {
173
      if( _transaction->getMCmd() == gs::Generic_MCMD_RD) {
174
        unsigned int address = static_cast<unsigned int>(_transaction->getMAddr()) - m_base;
175

    
176
        // re-creates byte enables.  Assumes addresses are correctly aligned
177
        unsigned int length = _transaction->getMBurstLength();
178
        unsigned int mask;
179
        switch(length) {
180
          case 1:
181
            mask = 0x1;
182
            break;
183
          case 2:
184
            mask = 0x3;
185
            break;
186
          case 3:
187
            mask = 0x7;
188
            break;
189
          case 4:
190
          default:
191
            mask = 0xF;
192
        }
193

    
194
        m_registers->bus_read(m_bus_read_data, address, mask, &_transaction,
195
                              m_delay_enabled);
196
        gs::GSDataType::dtype tmp((unsigned char *)(&m_bus_read_data),
197
                                  _transaction->getMBurstLength());
198
        gs::MData mdata(tmp);
199
        _transaction->setSData(mdata);
200
      } else if( _transaction->getMCmd() == gs::Generic_MCMD_WR) {
201
        unsigned int data;
202
        unsigned int address = static_cast<unsigned int>(_transaction->getMAddr()) - m_base;        
203
        unsigned int length = _transaction->getMBurstLength();
204
        
205
        memcpy(&data, &(_transaction->getMData()[0]), length);
206
        
207
        unsigned int mask; 
208
        switch(length)
209
        {
210
          case 1:
211
            mask = 0x1;
212
            break;
213
          case 2:
214
            mask = 0x3;
215
            break;
216
          case 3:
217
            mask = 0x7;
218
            break;
219
          case 4:
220
          default:
221
            mask = 0xF;
222
        }
223
        
224
        m_registers->bus_write( data, address, mask, &_transaction, m_delay_enabled);
225
      } else {
226
      }
227

    
228
      return( 1);
229
    }
230

    
231
  protected:
232
    sc_dt::uint64  m_base;
233
    sc_dt::uint64  m_high;
234
    
235
  private:
236
    unsigned int m_bus_read_data;
237
  };
238

    
239
  
240
  
241
  class generic_master
242
  //: public sc_core::sc_module
243
  : public tlm_components::transactor_if
244
  , public gs::payload_event_queue_output_if<gs::gp::master_atom>
245
  , public gs::gp::GenericMasterBlockingPort<32>
246
  {
247
  public:
248

    
249
    typedef gs::gp::GenericMasterBlockingPort<32>::accessHandle transactionHandle_master;
250
    typedef gs::gp::GenericMasterBlockingPort<32>::phase phase_master;
251
    typedef gs::gp::GenericMasterBlockingPort<32>::virtual_base_type virtual_base_type;
252

    
253
    SC_HAS_PROCESS( generic_master);
254

    
255
    generic_master( sc_core::sc_module_name _name)
256
    //: sc_core::sc_module( _name)
257
    : virtual_base_type( _name/*"master_port"*/, GSGP_MASTER_SOCKET_TYPE_NAME)
258
    , gs::gp::GenericMasterBlockingPort<32>( _name/*"master_port"*/)
259
    {
260
      gs::gp::GenericMasterBlockingPort<32>::out_port(*this);
261
    }
262

    
263
    virtual ~generic_master()
264
    {}
265

    
266
    // user methods - using default implementation in transactor_if
267
//    virtual unsigned int read( unsigned int _address, unsigned int _width);
268
//    virtual void write(unsigned int _address, unsigned int _data, unsigned int _width);
269

    
270
    virtual void random_read()
271
    {}
272

    
273
    virtual void random_write()
274
    {}
275

    
276
    virtual void notify(gs::gp::master_atom &tc)
277
    {}
278

    
279
  protected:
280
     transactionHandle_master transaction;
281
    
282
    // transactor methods
283
    virtual void _read(unsigned _address, unsigned _length, unsigned int* _db, bool _bytes_enabled, unsigned int* _be) {
284
      transaction = gs::gp::GenericMasterBlockingPort<32>::create_transaction();
285
      // fix because greenbus does not overwrite data block cleanly (even though the back end does)
286
      *_db = 0;
287

    
288
      transaction->setMCmd(gs::Generic_MCMD_RD);
289
      transaction->setMAddr( _address);
290
      transaction->setMBurstLength( _length);
291
      gs::MData mdata(gs::GSDataType::dtype((unsigned char *)_db, _length));
292
      transaction->setMData(mdata);
293

    
294
      gs::gp::GenericMasterBlockingPort<32>::Transact( transaction);
295
      
296
      gs::gp::GenericMasterBlockingPort<32>::release_transaction(transaction);
297
    }
298

    
299
    virtual void _write(unsigned _address, unsigned _length, unsigned int* _db, bool _bytes_enabled, unsigned int* _be) {
300
      transaction = gs::gp::GenericMasterBlockingPort<32>::create_transaction();
301
      
302
      transaction->setMCmd(gs::Generic_MCMD_WR);
303
      transaction->setMAddr( _address);
304
      transaction->setMBurstLength( _length);
305
      gs::MData mdata(gs::GSDataType::dtype((unsigned char *)_db, _length));
306
      transaction->setMData(mdata);
307
//        transaction->set_mData(::tlm::MasterDataType( reinterpret_cast< unsigned char *>( _db), _length));
308

    
309
      gs::gp::GenericMasterBlockingPort<32>::Transact( transaction);
310
      
311
      gs::gp::GenericMasterBlockingPort<32>::release_transaction(transaction);
312
    }
313

    
314
  private:
315
  };
316

    
317
} // end namespace gs::gp
318
} // end namespace gs::gp
319

    
320
#endif /*_GSGPSOCKET_H_*/