111818SChristian.Menard@tu-dresden.de/*
211818SChristian.Menard@tu-dresden.de * Copyright (c) 2015, University of Kaiserslautern
311818SChristian.Menard@tu-dresden.de * All rights reserved.
411818SChristian.Menard@tu-dresden.de *
511818SChristian.Menard@tu-dresden.de * Redistribution and use in source and binary forms, with or without
611818SChristian.Menard@tu-dresden.de * modification, are permitted provided that the following conditions are
711818SChristian.Menard@tu-dresden.de * met:
811818SChristian.Menard@tu-dresden.de *
911818SChristian.Menard@tu-dresden.de * 1. Redistributions of source code must retain the above copyright notice,
1011818SChristian.Menard@tu-dresden.de *    this list of conditions and the following disclaimer.
1111818SChristian.Menard@tu-dresden.de *
1211818SChristian.Menard@tu-dresden.de * 2. Redistributions in binary form must reproduce the above copyright
1311818SChristian.Menard@tu-dresden.de *    notice, this list of conditions and the following disclaimer in the
1411818SChristian.Menard@tu-dresden.de *    documentation and/or other materials provided with the distribution.
1511818SChristian.Menard@tu-dresden.de *
1611818SChristian.Menard@tu-dresden.de * 3. Neither the name of the copyright holder nor the names of its
1711818SChristian.Menard@tu-dresden.de *    contributors may be used to endorse or promote products derived from
1811818SChristian.Menard@tu-dresden.de *    this software without specific prior written permission.
1911818SChristian.Menard@tu-dresden.de *
2011818SChristian.Menard@tu-dresden.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2111818SChristian.Menard@tu-dresden.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2211818SChristian.Menard@tu-dresden.de * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2311818SChristian.Menard@tu-dresden.de * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
2411818SChristian.Menard@tu-dresden.de * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2511818SChristian.Menard@tu-dresden.de * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2611818SChristian.Menard@tu-dresden.de * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2711818SChristian.Menard@tu-dresden.de * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2811818SChristian.Menard@tu-dresden.de * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2911818SChristian.Menard@tu-dresden.de * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3011818SChristian.Menard@tu-dresden.de * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3111818SChristian.Menard@tu-dresden.de *
3211818SChristian.Menard@tu-dresden.de * Authors: Matthias Jung
3311818SChristian.Menard@tu-dresden.de */
3411818SChristian.Menard@tu-dresden.de
3511818SChristian.Menard@tu-dresden.de#include "sc_target.hh"
3611818SChristian.Menard@tu-dresden.de
3711818SChristian.Menard@tu-dresden.deusing namespace sc_core;
3811818SChristian.Menard@tu-dresden.deusing namespace std;
3911818SChristian.Menard@tu-dresden.de
4011818SChristian.Menard@tu-dresden.deTarget::Target(sc_core::sc_module_name name,
4111818SChristian.Menard@tu-dresden.de    bool debug,
4211818SChristian.Menard@tu-dresden.de    unsigned long long int size,
4311818SChristian.Menard@tu-dresden.de    unsigned int offset) :
4411818SChristian.Menard@tu-dresden.de    socket("socket"),
4511818SChristian.Menard@tu-dresden.de    transaction_in_progress(0),
4611818SChristian.Menard@tu-dresden.de    response_in_progress(false),
4711818SChristian.Menard@tu-dresden.de    next_response_pending(0),
4811818SChristian.Menard@tu-dresden.de    end_req_pending(0),
4911818SChristian.Menard@tu-dresden.de    m_peq(this, &Target::peq_cb),
5011818SChristian.Menard@tu-dresden.de    debug(debug),
5111818SChristian.Menard@tu-dresden.de    size(size),
5211818SChristian.Menard@tu-dresden.de    offset(offset)
5311818SChristian.Menard@tu-dresden.de{
5411818SChristian.Menard@tu-dresden.de    /* Register tlm transport functions */
5511818SChristian.Menard@tu-dresden.de    socket.register_b_transport(this, &Target::b_transport);
5611818SChristian.Menard@tu-dresden.de    socket.register_transport_dbg(this, &Target::transport_dbg);
5711818SChristian.Menard@tu-dresden.de    socket.register_nb_transport_fw(this, &Target::nb_transport_fw);
5811818SChristian.Menard@tu-dresden.de
5911818SChristian.Menard@tu-dresden.de
6011818SChristian.Menard@tu-dresden.de    /* allocate storage memory */
6111818SChristian.Menard@tu-dresden.de    mem = new unsigned char[size];
6211818SChristian.Menard@tu-dresden.de
6311818SChristian.Menard@tu-dresden.de    SC_METHOD(execute_transaction_process);
6411818SChristian.Menard@tu-dresden.de    sensitive << target_done_event;
6511818SChristian.Menard@tu-dresden.de    dont_initialize();
6611818SChristian.Menard@tu-dresden.de}
6711818SChristian.Menard@tu-dresden.de
6811818SChristian.Menard@tu-dresden.devoid
6912048Schristian.menard@tu-dresden.deTarget::check_address(unsigned long long int addr)
7012048Schristian.menard@tu-dresden.de{
7112048Schristian.menard@tu-dresden.de    if (addr < offset || addr >= offset + size)
7212048Schristian.menard@tu-dresden.de        SC_REPORT_FATAL("Target", "Address out of range. Did you set an "
7312048Schristian.menard@tu-dresden.de                                  "appropriate size and offset?");
7412048Schristian.menard@tu-dresden.de}
7512048Schristian.menard@tu-dresden.de
7612048Schristian.menard@tu-dresden.devoid
7711818SChristian.Menard@tu-dresden.deTarget::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay)
7811818SChristian.Menard@tu-dresden.de{
7911818SChristian.Menard@tu-dresden.de    /* Execute the read or write commands */
8011818SChristian.Menard@tu-dresden.de    execute_transaction(trans);
8111818SChristian.Menard@tu-dresden.de}
8211818SChristian.Menard@tu-dresden.de
8311818SChristian.Menard@tu-dresden.deunsigned int
8411818SChristian.Menard@tu-dresden.deTarget::transport_dbg(tlm::tlm_generic_payload& trans)
8511818SChristian.Menard@tu-dresden.de{
8612048Schristian.menard@tu-dresden.de    check_address(trans.get_address());
8712048Schristian.menard@tu-dresden.de
8811818SChristian.Menard@tu-dresden.de    tlm::tlm_command cmd = trans.get_command();
8911818SChristian.Menard@tu-dresden.de    sc_dt::uint64    adr = trans.get_address() - offset;
9011818SChristian.Menard@tu-dresden.de    unsigned char*   ptr = trans.get_data_ptr();
9111818SChristian.Menard@tu-dresden.de    unsigned int     len = trans.get_data_length();
9211818SChristian.Menard@tu-dresden.de
9311818SChristian.Menard@tu-dresden.de    unsigned char *mem_array_ptr = mem + adr;
9411818SChristian.Menard@tu-dresden.de
9511818SChristian.Menard@tu-dresden.de    /* Load / Store the access: */
9611818SChristian.Menard@tu-dresden.de    if ( cmd == tlm::TLM_READ_COMMAND ) {
9711818SChristian.Menard@tu-dresden.de        if (debug) {
9811818SChristian.Menard@tu-dresden.de            SC_REPORT_INFO("target", "tlm::TLM_READ_COMMAND");
9911818SChristian.Menard@tu-dresden.de        }
10011818SChristian.Menard@tu-dresden.de        std::memcpy(ptr, mem_array_ptr, len);
10111818SChristian.Menard@tu-dresden.de    } else if ( cmd == tlm::TLM_WRITE_COMMAND ) {
10211818SChristian.Menard@tu-dresden.de        if (debug) {
10311818SChristian.Menard@tu-dresden.de            SC_REPORT_INFO("target", "tlm::TLM_WRITE_COMMAND");
10411818SChristian.Menard@tu-dresden.de        }
10511818SChristian.Menard@tu-dresden.de        std::memcpy(mem_array_ptr, ptr, len);
10611818SChristian.Menard@tu-dresden.de    }
10711818SChristian.Menard@tu-dresden.de
10811818SChristian.Menard@tu-dresden.de    return len;
10911818SChristian.Menard@tu-dresden.de}
11011818SChristian.Menard@tu-dresden.de
11111818SChristian.Menard@tu-dresden.de
11211818SChristian.Menard@tu-dresden.de/* TLM-2 non-blocking transport method */
11311818SChristian.Menard@tu-dresden.detlm::tlm_sync_enum Target::nb_transport_fw(tlm::tlm_generic_payload& trans,
11411818SChristian.Menard@tu-dresden.de                                           tlm::tlm_phase& phase,
11511818SChristian.Menard@tu-dresden.de                                           sc_time& delay)
11611818SChristian.Menard@tu-dresden.de{
11711818SChristian.Menard@tu-dresden.de    /* Queue the transaction until the annotated time has elapsed */
11811818SChristian.Menard@tu-dresden.de    m_peq.notify(trans, phase, delay);
11911818SChristian.Menard@tu-dresden.de    return tlm::TLM_ACCEPTED;
12011818SChristian.Menard@tu-dresden.de}
12111818SChristian.Menard@tu-dresden.de
12211818SChristian.Menard@tu-dresden.devoid
12311818SChristian.Menard@tu-dresden.deTarget::peq_cb(tlm::tlm_generic_payload& trans,
12411818SChristian.Menard@tu-dresden.de               const tlm::tlm_phase& phase)
12511818SChristian.Menard@tu-dresden.de{
12611818SChristian.Menard@tu-dresden.de    sc_time delay;
12711818SChristian.Menard@tu-dresden.de
12811818SChristian.Menard@tu-dresden.de    if (phase == tlm::BEGIN_REQ) {
12911818SChristian.Menard@tu-dresden.de        if (debug) SC_REPORT_INFO("target", "tlm::BEGIN_REQ");
13011818SChristian.Menard@tu-dresden.de
13111818SChristian.Menard@tu-dresden.de        /* Increment the transaction reference count */
13211818SChristian.Menard@tu-dresden.de        trans.acquire();
13311818SChristian.Menard@tu-dresden.de
13411818SChristian.Menard@tu-dresden.de        if ( !transaction_in_progress ) {
13511818SChristian.Menard@tu-dresden.de            send_end_req(trans);
13611818SChristian.Menard@tu-dresden.de        } else {
13711818SChristian.Menard@tu-dresden.de            /* Put back-pressure on initiator by deferring END_REQ until
13811818SChristian.Menard@tu-dresden.de             * pipeline is clear */
13911818SChristian.Menard@tu-dresden.de            end_req_pending = &trans;
14011818SChristian.Menard@tu-dresden.de        }
14111818SChristian.Menard@tu-dresden.de    } else if (phase == tlm::END_RESP) {
14211818SChristian.Menard@tu-dresden.de        /* On receiving END_RESP, the target can release the transaction and
14311818SChristian.Menard@tu-dresden.de         * allow other pending transactions to proceed */
14411818SChristian.Menard@tu-dresden.de        if (!response_in_progress) {
14511818SChristian.Menard@tu-dresden.de            SC_REPORT_FATAL("TLM-2", "Illegal transaction phase END_RESP"
14611818SChristian.Menard@tu-dresden.de                            "received by target");
14711818SChristian.Menard@tu-dresden.de        }
14811818SChristian.Menard@tu-dresden.de
14911818SChristian.Menard@tu-dresden.de        transaction_in_progress = 0;
15011818SChristian.Menard@tu-dresden.de
15111818SChristian.Menard@tu-dresden.de        /* Target itself is now clear to issue the next BEGIN_RESP */
15211818SChristian.Menard@tu-dresden.de        response_in_progress = false;
15311818SChristian.Menard@tu-dresden.de        if (next_response_pending) {
15411818SChristian.Menard@tu-dresden.de            send_response( *next_response_pending );
15511818SChristian.Menard@tu-dresden.de            next_response_pending = 0;
15611818SChristian.Menard@tu-dresden.de        }
15711818SChristian.Menard@tu-dresden.de
15811818SChristian.Menard@tu-dresden.de        /* ... and to unblock the initiator by issuing END_REQ */
15911818SChristian.Menard@tu-dresden.de        if (end_req_pending) {
16011818SChristian.Menard@tu-dresden.de            send_end_req( *end_req_pending );
16111818SChristian.Menard@tu-dresden.de            end_req_pending = 0;
16211818SChristian.Menard@tu-dresden.de        }
16311818SChristian.Menard@tu-dresden.de
16411818SChristian.Menard@tu-dresden.de    } else /* tlm::END_REQ or tlm::BEGIN_RESP */ {
16511818SChristian.Menard@tu-dresden.de            SC_REPORT_FATAL("TLM-2", "Illegal transaction phase received by"
16611818SChristian.Menard@tu-dresden.de                            "target");
16711818SChristian.Menard@tu-dresden.de    }
16811818SChristian.Menard@tu-dresden.de}
16911818SChristian.Menard@tu-dresden.de
17011818SChristian.Menard@tu-dresden.devoid
17111818SChristian.Menard@tu-dresden.deTarget::send_end_req(tlm::tlm_generic_payload& trans)
17211818SChristian.Menard@tu-dresden.de{
17311818SChristian.Menard@tu-dresden.de    tlm::tlm_phase bw_phase;
17411818SChristian.Menard@tu-dresden.de    sc_time delay;
17511818SChristian.Menard@tu-dresden.de
17611818SChristian.Menard@tu-dresden.de    /* Queue the acceptance and the response with the appropriate latency */
17711818SChristian.Menard@tu-dresden.de    bw_phase = tlm::END_REQ;
17811818SChristian.Menard@tu-dresden.de    delay = sc_time(10.0, SC_NS); // Accept delay
17911818SChristian.Menard@tu-dresden.de
18011818SChristian.Menard@tu-dresden.de    tlm::tlm_sync_enum status;
18111818SChristian.Menard@tu-dresden.de    status = socket->nb_transport_bw(trans, bw_phase, delay);
18211818SChristian.Menard@tu-dresden.de
18311818SChristian.Menard@tu-dresden.de    /* Ignore return value;
18411818SChristian.Menard@tu-dresden.de     * initiator cannot terminate transaction at this point
18511818SChristian.Menard@tu-dresden.de     * Queue internal event to mark beginning of response: */
18611818SChristian.Menard@tu-dresden.de    delay = delay + sc_time(40.0, SC_NS); // Latency
18711818SChristian.Menard@tu-dresden.de    target_done_event.notify(delay);
18811818SChristian.Menard@tu-dresden.de
18911818SChristian.Menard@tu-dresden.de    assert(transaction_in_progress == 0);
19011818SChristian.Menard@tu-dresden.de    transaction_in_progress = &trans;
19111818SChristian.Menard@tu-dresden.de}
19211818SChristian.Menard@tu-dresden.de
19311818SChristian.Menard@tu-dresden.devoid
19411818SChristian.Menard@tu-dresden.deTarget::execute_transaction_process()
19511818SChristian.Menard@tu-dresden.de{
19611818SChristian.Menard@tu-dresden.de    /* Execute the read or write commands */
19711818SChristian.Menard@tu-dresden.de    execute_transaction( *transaction_in_progress );
19811818SChristian.Menard@tu-dresden.de
19911818SChristian.Menard@tu-dresden.de    /* Target must honor BEGIN_RESP/END_RESP exclusion rule; i.e. must not
20011818SChristian.Menard@tu-dresden.de     * send BEGIN_RESP until receiving previous END_RESP or BEGIN_REQ */
20111818SChristian.Menard@tu-dresden.de    if (response_in_progress) {
20211818SChristian.Menard@tu-dresden.de        /* Target allows only two transactions in-flight */
20311818SChristian.Menard@tu-dresden.de        if (next_response_pending) {
20411818SChristian.Menard@tu-dresden.de            SC_REPORT_FATAL("TLM-2", "Attempt to have two pending responses"
20511818SChristian.Menard@tu-dresden.de                            "in target");
20611818SChristian.Menard@tu-dresden.de        }
20711818SChristian.Menard@tu-dresden.de        next_response_pending = transaction_in_progress;
20811818SChristian.Menard@tu-dresden.de    } else {
20911818SChristian.Menard@tu-dresden.de        send_response( *transaction_in_progress );
21011818SChristian.Menard@tu-dresden.de    }
21111818SChristian.Menard@tu-dresden.de}
21211818SChristian.Menard@tu-dresden.de
21311818SChristian.Menard@tu-dresden.devoid
21411818SChristian.Menard@tu-dresden.deTarget::execute_transaction(tlm::tlm_generic_payload& trans)
21511818SChristian.Menard@tu-dresden.de{
21612048Schristian.menard@tu-dresden.de    check_address(trans.get_address());
21712048Schristian.menard@tu-dresden.de
21811818SChristian.Menard@tu-dresden.de    tlm::tlm_command cmd = trans.get_command();
21911818SChristian.Menard@tu-dresden.de    sc_dt::uint64    adr = trans.get_address() - offset;
22011818SChristian.Menard@tu-dresden.de    unsigned char*   ptr = trans.get_data_ptr();
22111818SChristian.Menard@tu-dresden.de    unsigned int     len = trans.get_data_length();
22211818SChristian.Menard@tu-dresden.de    unsigned char*   byt = trans.get_byte_enable_ptr();
22311818SChristian.Menard@tu-dresden.de    unsigned int     wid = trans.get_streaming_width();
22411818SChristian.Menard@tu-dresden.de
22511818SChristian.Menard@tu-dresden.de    if ( byt != 0 ) {
22611818SChristian.Menard@tu-dresden.de        cout << "Byte Error" << endl;
22711818SChristian.Menard@tu-dresden.de        trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE );
22811818SChristian.Menard@tu-dresden.de        return;
22911818SChristian.Menard@tu-dresden.de    }
23011818SChristian.Menard@tu-dresden.de
23111818SChristian.Menard@tu-dresden.de    //if ( len > 4 || wid < len ) {
23211818SChristian.Menard@tu-dresden.de    //    cout << "Burst Error len=" << len << " wid=" << wid << endl;
23311818SChristian.Menard@tu-dresden.de    //    trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE );
23411818SChristian.Menard@tu-dresden.de    //    return;
23511818SChristian.Menard@tu-dresden.de    //}
23611818SChristian.Menard@tu-dresden.de
23711818SChristian.Menard@tu-dresden.de    unsigned char *mem_array_ptr = mem + adr;
23811818SChristian.Menard@tu-dresden.de
23911818SChristian.Menard@tu-dresden.de    /* Load / Store the access: */
24011818SChristian.Menard@tu-dresden.de    if ( cmd == tlm::TLM_READ_COMMAND ) {
24111818SChristian.Menard@tu-dresden.de        if (debug) {
24211818SChristian.Menard@tu-dresden.de            SC_REPORT_INFO("target", "tlm::TLM_READ_COMMAND");
24311818SChristian.Menard@tu-dresden.de        }
24411818SChristian.Menard@tu-dresden.de        std::memcpy(ptr, mem_array_ptr, len);
24511818SChristian.Menard@tu-dresden.de    } else if ( cmd == tlm::TLM_WRITE_COMMAND ) {
24611818SChristian.Menard@tu-dresden.de        if (debug) {
24711818SChristian.Menard@tu-dresden.de            SC_REPORT_INFO("target", "tlm::TLM_WRITE_COMMAND");
24811818SChristian.Menard@tu-dresden.de        }
24911818SChristian.Menard@tu-dresden.de        std::memcpy(mem_array_ptr, ptr, len);
25011818SChristian.Menard@tu-dresden.de    }
25111818SChristian.Menard@tu-dresden.de
25211818SChristian.Menard@tu-dresden.de    trans.set_response_status( tlm::TLM_OK_RESPONSE );
25311818SChristian.Menard@tu-dresden.de}
25411818SChristian.Menard@tu-dresden.de
25511818SChristian.Menard@tu-dresden.devoid
25611818SChristian.Menard@tu-dresden.deTarget::send_response(tlm::tlm_generic_payload& trans)
25711818SChristian.Menard@tu-dresden.de{
25811818SChristian.Menard@tu-dresden.de    tlm::tlm_sync_enum status;
25911818SChristian.Menard@tu-dresden.de    tlm::tlm_phase bw_phase;
26011818SChristian.Menard@tu-dresden.de    sc_time delay;
26111818SChristian.Menard@tu-dresden.de
26211818SChristian.Menard@tu-dresden.de    response_in_progress = true;
26311818SChristian.Menard@tu-dresden.de    bw_phase = tlm::BEGIN_RESP;
26411818SChristian.Menard@tu-dresden.de    delay = sc_time(10.0, SC_NS);
26511818SChristian.Menard@tu-dresden.de    status = socket->nb_transport_bw( trans, bw_phase, delay );
26611818SChristian.Menard@tu-dresden.de
26711818SChristian.Menard@tu-dresden.de    if (status == tlm::TLM_UPDATED) {
26811818SChristian.Menard@tu-dresden.de        /* The timing annotation must be honored */
26911818SChristian.Menard@tu-dresden.de        m_peq.notify(trans, bw_phase, delay);
27011818SChristian.Menard@tu-dresden.de    } else if (status == tlm::TLM_COMPLETED) {
27111818SChristian.Menard@tu-dresden.de        /* The initiator has terminated the transaction */
27211818SChristian.Menard@tu-dresden.de        transaction_in_progress = 0;
27311818SChristian.Menard@tu-dresden.de        response_in_progress = false;
27411818SChristian.Menard@tu-dresden.de    }
27511818SChristian.Menard@tu-dresden.de    trans.release();
27611818SChristian.Menard@tu-dresden.de}
277