1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20#ifndef __SIMPLE_LT_TARGET1_H__
21#define __SIMPLE_LT_TARGET1_H__
22
23#include "tlm.h"
24#include <cassert>
25#include <vector>
26
27class SimpleLTTarget1 :
28  public sc_core::sc_module,
29  public virtual tlm::tlm_fw_transport_if<>
30{
31public:
32  typedef tlm::tlm_generic_payload      transaction_type;
33  typedef tlm::tlm_phase                phase_type;
34  typedef tlm::tlm_sync_enum            sync_enum_type;
35  typedef tlm::tlm_fw_transport_if<>    fw_interface_type;
36  typedef tlm::tlm_bw_transport_if<>    bw_interface_type;
37  typedef tlm::tlm_target_socket<32>    target_socket_type;
38
39public:
40  target_socket_type socket;
41
42public:
43  SC_HAS_PROCESS(SimpleLTTarget1);
44  SimpleLTTarget1(sc_core::sc_module_name name, bool invalidate = false) :
45      sc_core::sc_module(name),
46      socket("socket"),
47      m_invalidate(invalidate)
48  {
49    // Bind this target's interface to the target socket
50    socket(*this);
51    if (invalidate)
52    {
53        SC_METHOD(invalidate_dmi_method);
54        sensitive << m_invalidate_dmi_event;
55        dont_initialize();
56        m_invalidate_dmi_time = sc_core::sc_time(25, sc_core::SC_NS);
57    }
58  }
59
60  sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t)
61  {
62    //Target never calls wait, so we can do this
63    b_transport(trans, t);
64
65    return tlm::TLM_COMPLETED;
66  }
67
68  void b_transport(transaction_type& trans, sc_core::sc_time &t)
69  {
70    sc_dt::uint64 address = trans.get_address();
71    assert(address < 400);
72
73    unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr());
74    if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
75      std::cout << name() << ": Received write request: A = 0x"
76                << std::hex << (unsigned int)address
77                << ", D = 0x" << data << std::dec
78                << " @ " << sc_core::sc_time_stamp() << std::endl;
79
80      *reinterpret_cast<unsigned int*>(&mMem[address]) = data;
81      t+=  sc_core::sc_time(10, sc_core::SC_NS);
82
83    } else {
84      std::cout << name() << ": Received read request: A = 0x"
85                << std::hex << (unsigned int)address << std::dec
86                << " @ " << sc_core::sc_time_stamp() << std::endl;
87
88      data = *reinterpret_cast<unsigned int*>(&mMem[address]);
89      t += sc_core::sc_time(100, sc_core::SC_NS);
90    }
91
92    trans.set_response_status(tlm::TLM_OK_RESPONSE);
93
94    trans.set_dmi_allowed(true);
95  }
96
97  unsigned int transport_dbg(transaction_type& r)
98  {
99    if (r.get_address() >= 400) return 0;
100
101    unsigned int tmp = (int)r.get_address();
102    unsigned int num_bytes;
103    if (tmp + r.get_data_length() >= 400) {
104      num_bytes = 400 - tmp;
105
106    } else {
107      num_bytes = r.get_data_length();
108    }
109    if (r.is_read()) {
110      for (unsigned int i = 0; i < num_bytes; ++i) {
111        r.get_data_ptr()[i] = mMem[i + tmp];
112      }
113
114    } else {
115      for (unsigned int i = 0; i < num_bytes; ++i) {
116        mMem[i + tmp] = r.get_data_ptr()[i];
117      }
118    }
119    return num_bytes;
120  }
121
122  bool get_direct_mem_ptr(transaction_type& trans,
123                          tlm::tlm_dmi&  dmi_data)
124  {
125    sc_dt::uint64 address = trans.get_address();
126    if (m_invalidate) m_invalidate_dmi_event.notify(m_invalidate_dmi_time);
127    if (address < 400) {
128      dmi_data.allow_read_write();
129      dmi_data.set_start_address(0x0);
130      dmi_data.set_end_address(399);
131      dmi_data.set_dmi_ptr(mMem);
132      dmi_data.set_read_latency(sc_core::sc_time(100, sc_core::SC_NS));
133      dmi_data.set_write_latency(sc_core::sc_time(10, sc_core::SC_NS));
134      return true;
135
136    } else {
137      // should not happen
138      dmi_data.set_start_address(trans.get_address());
139      dmi_data.set_end_address(trans.get_address());
140      return false;
141
142    }
143  }
144
145  void invalidate_dmi_method()
146  {
147      sc_dt::uint64 start_address = 0x0;
148      sc_dt::uint64 end_address = 399;
149      socket->invalidate_direct_mem_ptr(start_address, end_address);
150  }
151private:
152  unsigned char mMem[400];
153  bool              m_invalidate;
154  sc_core::sc_event m_invalidate_dmi_event;
155  sc_core::sc_time  m_invalidate_dmi_time;
156};
157
158#endif
159