ExplicitATTarget.h revision 12922
1955SN/A/*****************************************************************************
2955SN/A
31762SN/A  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4955SN/A  more contributor license agreements.  See the NOTICE file distributed
5955SN/A  with this work for additional information regarding copyright ownership.
6955SN/A  Accellera licenses this file to you under the Apache License, Version 2.0
7955SN/A  (the "License"); you may not use this file except in compliance with the
8955SN/A  License.  You may obtain a copy of the License at
9955SN/A
10955SN/A    http://www.apache.org/licenses/LICENSE-2.0
11955SN/A
12955SN/A  Unless required by applicable law or agreed to in writing, software
13955SN/A  distributed under the License is distributed on an "AS IS" BASIS,
14955SN/A  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15955SN/A  implied.  See the License for the specific language governing
16955SN/A  permissions and limitations under the License.
17955SN/A
18955SN/A *****************************************************************************/
19955SN/A
20955SN/A#ifndef __EXPLICIT_AT_TARGET_H__
21955SN/A#define __EXPLICIT_AT_TARGET_H__
22955SN/A
23955SN/A#include "tlm.h"
24955SN/A#include "tlm_utils/simple_target_socket.h"
25955SN/A//#include <systemc>
26955SN/A#include <cassert>
27955SN/A#include <vector>
282665Ssaidi@eecs.umich.edu#include <queue>
294762Snate@binkert.org//#include <iostream>
30955SN/A
315522Snate@binkert.orgclass ExplicitATTarget : public sc_core::sc_module
324762Snate@binkert.org{
335522Snate@binkert.orgpublic:
34955SN/A  typedef tlm::tlm_generic_payload                 transaction_type;
355522Snate@binkert.org  typedef tlm::tlm_phase                           phase_type;
36955SN/A  typedef tlm::tlm_sync_enum                       sync_enum_type;
375522Snate@binkert.org  typedef tlm_utils::simple_target_socket<ExplicitATTarget>     target_socket_type;
384202Sbinkertn@umich.edu
395742Snate@binkert.orgpublic:
40955SN/A  target_socket_type socket;
414381Sbinkertn@umich.edu
424381Sbinkertn@umich.edupublic:
43955SN/A  SC_HAS_PROCESS(ExplicitATTarget);
44955SN/A  ExplicitATTarget(sc_core::sc_module_name name) :
45955SN/A    sc_core::sc_module(name),
464202Sbinkertn@umich.edu    socket("socket"),
47955SN/A    mCurrentTransaction(0)
484382Sbinkertn@umich.edu  {
494382Sbinkertn@umich.edu    // register nb_transport method
504382Sbinkertn@umich.edu    socket.register_nb_transport_fw(this, &ExplicitATTarget::myNBTransport);
516108Snate@binkert.org    socket.register_transport_dbg(this, &ExplicitATTarget::transport_dbg);
525517Snate@binkert.org
534762Snate@binkert.org    SC_THREAD(beginResponse)
544762Snate@binkert.org  }
554762Snate@binkert.org
564762Snate@binkert.org  sync_enum_type myNBTransport(transaction_type& trans, phase_type& phase, sc_core::sc_time& t)
574762Snate@binkert.org  {
584762Snate@binkert.org    if (phase == tlm::BEGIN_REQ) {
594762Snate@binkert.org      sc_dt::uint64 address = trans.get_address();
604762Snate@binkert.org      assert(address < 400);
614762Snate@binkert.org
624762Snate@binkert.org      // This target only supports one transaction at a time
635522Snate@binkert.org      // This will only work with LT initiators
645604Snate@binkert.org      assert(mCurrentTransaction == 0);
655604Snate@binkert.org
665604Snate@binkert.org      unsigned int& data = *reinterpret_cast<unsigned int*>(trans.get_data_ptr());
674762Snate@binkert.org      if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
684762Snate@binkert.org        std::cout << name() << ": Received write request: A = 0x"
694762Snate@binkert.org                  << std::hex << (unsigned int)address << ", D = 0x" << data
705522Snate@binkert.org                  << std::dec << " @ " << sc_core::sc_time_stamp()
715522Snate@binkert.org                  << std::endl;
725522Snate@binkert.org
735522Snate@binkert.org        *reinterpret_cast<unsigned int*>(&mMem[address]) = data;
745604Snate@binkert.org
755604Snate@binkert.org        // Synchronization on demand (eg need to assert an interrupt)
764762Snate@binkert.org        mResponseEvent.notify(t);
774762Snate@binkert.org        mCurrentTransaction = &trans;
784762Snate@binkert.org
794762Snate@binkert.org        // End request phase
805522Snate@binkert.org        phase = tlm::END_REQ;
814762Snate@binkert.org        return tlm::TLM_UPDATED;
824762Snate@binkert.org
835604Snate@binkert.org      } else {
845604Snate@binkert.org        std::cout << name() << ": Received read request: A = 0x"
855604Snate@binkert.org                  << std::hex << (unsigned int)address
865604Snate@binkert.org                  << std::dec << " @ " << sc_core::sc_time_stamp()
875604Snate@binkert.org                  << std::endl;
885604Snate@binkert.org
894762Snate@binkert.org        data = *reinterpret_cast<unsigned int*>(&mMem[address]);
904762Snate@binkert.org        trans.set_response_status(tlm::TLM_OK_RESPONSE);
914762Snate@binkert.org
924762Snate@binkert.org        // Finish transaction (use timing annotation)
935604Snate@binkert.org        t += sc_core::sc_time(100, sc_core::SC_NS);
944762Snate@binkert.org        return tlm::TLM_COMPLETED;
955522Snate@binkert.org      }
965522Snate@binkert.org
975522Snate@binkert.org    } else if (phase == tlm::END_RESP) {
984762Snate@binkert.org
994382Sbinkertn@umich.edu      // Transaction finished
1004762Snate@binkert.org      mCurrentTransaction = 0;
1014382Sbinkertn@umich.edu      return tlm::TLM_COMPLETED;
1025522Snate@binkert.org    }
1034381Sbinkertn@umich.edu
1045522Snate@binkert.org    // Not possible
1054762Snate@binkert.org    assert(0); exit(1);
1064762Snate@binkert.org//    return tlm::TLM_COMPLETED;  //unreachable code
1074762Snate@binkert.org  }
1085522Snate@binkert.org
1095522Snate@binkert.org  void beginResponse()
1105522Snate@binkert.org  {
1115522Snate@binkert.org    while (true) {
1125522Snate@binkert.org      // Wait for next synchronization request
1135522Snate@binkert.org      wait(mResponseEvent);
1145522Snate@binkert.org
1155522Snate@binkert.org      assert(mCurrentTransaction);
1165522Snate@binkert.org      // start response phase
1174762Snate@binkert.org      phase_type phase = tlm::BEGIN_RESP;
1184762Snate@binkert.org      sc_core::sc_time t = sc_core::SC_ZERO_TIME;
1194762Snate@binkert.org
1204762Snate@binkert.org      // Set response data
1214762Snate@binkert.org      mCurrentTransaction->set_response_status(tlm::TLM_OK_RESPONSE);
1224762Snate@binkert.org      assert(mCurrentTransaction->get_command() == tlm::TLM_WRITE_COMMAND);
1234762Snate@binkert.org
1244762Snate@binkert.org      sc_dt::uint64 address = mCurrentTransaction->get_address();
1254762Snate@binkert.org      assert(address < 400);
1264762Snate@binkert.org      *reinterpret_cast<unsigned int*>(mCurrentTransaction->get_data_ptr()) =
1274762Snate@binkert.org        *reinterpret_cast<unsigned int*>(&mMem[address]);
1284762Snate@binkert.org
1294762Snate@binkert.org      // We are synchronized, we can read/write sc_signals, wait,...
1304762Snate@binkert.org      // Wait before sending the response
1314762Snate@binkert.org      wait(50, sc_core::SC_NS);
1324762Snate@binkert.org
1334762Snate@binkert.org      if (socket->nb_transport_bw(*mCurrentTransaction, phase, t) == tlm::TLM_COMPLETED) {
1344762Snate@binkert.org        mCurrentTransaction = 0;
1354762Snate@binkert.org
1364762Snate@binkert.org      } else {
1374762Snate@binkert.org        // Initiator will call nb_transport(trans, END_RESP, t)
1384762Snate@binkert.org      }
1394762Snate@binkert.org    }
1404762Snate@binkert.org  }
1414762Snate@binkert.org
1424762Snate@binkert.org  unsigned int transport_dbg(transaction_type& r)
1434762Snate@binkert.org  {
1444762Snate@binkert.org    if (r.get_address() >= 400) return 0;
1454762Snate@binkert.org
1464762Snate@binkert.org    unsigned int tmp = (int)r.get_address();
1474762Snate@binkert.org    unsigned int num_bytes;
1484762Snate@binkert.org    if (tmp + r.get_data_length() >= 400) {
1494762Snate@binkert.org      num_bytes = 400 - tmp;
1504762Snate@binkert.org
1514762Snate@binkert.org    } else {
152955SN/A      num_bytes = r.get_data_length();
1535584Snate@binkert.org    }
1545584Snate@binkert.org    if (!r.is_read() && !r.is_write()) {
1555584Snate@binkert.org      return 0;
1565584Snate@binkert.org	}
1575584Snate@binkert.org    if (r.is_read()) {
1585584Snate@binkert.org      for (unsigned int i = 0; i < num_bytes; ++i) {
1595584Snate@binkert.org        r.get_data_ptr()[i] = mMem[i + tmp];
1605584Snate@binkert.org      }
1615584Snate@binkert.org
1625584Snate@binkert.org    } else {
1635584Snate@binkert.org      for (unsigned int i = 0; i < num_bytes; ++i) {
1645584Snate@binkert.org        mMem[i + tmp] = r.get_data_ptr()[i];
1655584Snate@binkert.org      }
1664382Sbinkertn@umich.edu    }
1674202Sbinkertn@umich.edu    return num_bytes;
1685522Snate@binkert.org  }
1694382Sbinkertn@umich.edu
1704382Sbinkertn@umich.eduprivate:
1714382Sbinkertn@umich.edu  unsigned char mMem[400];
1725584Snate@binkert.org  sc_core::sc_event mResponseEvent;
1734382Sbinkertn@umich.edu  transaction_type* mCurrentTransaction;
1744382Sbinkertn@umich.edu};
1754382Sbinkertn@umich.edu
1765192Ssaidi@eecs.umich.edu#endif
1775192Ssaidi@eecs.umich.edu