scc 2025.09
SystemC components library
tl_uh_bfm.cpp
1/*******************************************************************************
2 * Copyright (C) 2018 MINRES Technologies GmbH
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *******************************************************************************/
32#include "tl_uh_bfm.h"
33#include <scc/report.h>
34#include <scc/utilities.h>
35
36namespace sysc {
37
38using namespace sc_core;
39
40tl_uh_bfm::tl_uh_bfm(sc_module_name nm, int64_t offset)
41: sc_module(nm)
42, offset(offset)
43, NAMED(socket)
44, NAMED(clock)
45, NAMED(reset)
46, NAMED(a_bits_address)
47, NAMED(a_bits_data)
48, NAMED(a_ready)
49, NAMED(a_valid)
50, NAMED(a_bits_opcode)
51, NAMED(a_bits_param)
52, NAMED(a_bits_size)
53, NAMED(a_bits_source)
54, NAMED(a_bits_mask)
55, NAMED(a_bits_corrupt)
56, NAMED(d_bits_data)
57, NAMED(d_ready)
58, NAMED(d_valid)
59, NAMED(d_bits_opcode)
60, NAMED(d_bits_size)
61, NAMED(d_bits_source)
62, NAMED(fw_queue) {
63 socket.register_nb_transport_fw(
64 [this](tlm::tlm_generic_payload& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) -> tlm::tlm_sync_enum {
65 if(phase == tlm::BEGIN_REQ && gp.get_command() != tlm::TLM_IGNORE_COMMAND) {
66 gp.acquire();
67 fw_queue.notify(gp, delay);
68 return tlm::TLM_ACCEPTED;
69 } else if(phase == tlm::END_RESP) {
70 gp.release();
71 d_ready = true;
72 }
73 });
74
75 SC_METHOD(tl_response_method);
76 sensitive << clock.pos();
77 SC_THREAD(fw_thread);
78}
79
80tl_uh_bfm::~tl_uh_bfm() = default;
81
82void tl_uh_bfm::fw_thread() {
83 d_ready = true;
84 while(true) {
85 a_valid = false;
86 wait(fw_queue.get_event());
87 auto gp = fw_queue.get_next_transaction();
88 if(gp->get_data_length() == 4) {
89 auto addr = gp->get_address() + offset;
90 a_bits_address = addr;
91 a_valid = true;
92 a_bits_param = 0;
93 a_bits_size = 2; // 2^2 bytes
94 a_bits_source = 0x55;
95 a_bits_mask = 0xf;
96 a_bits_corrupt = false;
97 if(gp->get_command() == tlm::TLM_WRITE_COMMAND) {
98 a_bits_opcode = PutFullData;
99 a_bits_data = *(uint32_t*)gp->get_data_ptr();
100 } else {
101 a_bits_opcode = Get;
102 a_bits_data = 0;
103 }
104 tl_in_progress.push_back(gp);
105 do {
106 wait(clock.posedge_event());
107 } while(a_ready == false);
108 } else
109 SCCERR("tlbfm") << "Got transaction with unequal length";
110 }
111}
112
113void tl_uh_bfm::tl_response_method() {
114 if(d_valid && d_ready) {
115 // if(d_bits_source==0x55){ // this is ours
116 auto gp = tl_in_progress.front();
117 sc_assert(gp && "Got TL response without a request in queue");
118 tl_in_progress.pop_front();
119 if(gp->get_command() == tlm::TLM_WRITE_COMMAND) {
120 sc_assert(d_bits_opcode == AccessAck && "TL did not respond with AccessAck to write request");
121 } else {
122 sc_assert(d_bits_opcode == AccessAckData && "TL did not respond with AccessAckData to read request");
123 *(uint32_t*)(gp->get_data_ptr()) = d_bits_data;
124 }
125 gp->set_response_status(tlm::TLM_OK_RESPONSE);
126 sc_core::sc_time delay;
127 tlm::tlm_phase phase{tlm::BEGIN_RESP};
128 auto ret = socket->nb_transport_bw(*gp, phase, delay);
129 if(ret == tlm::TLM_COMPLETED || (ret == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
130 d_ready = true;
131 gp->release();
132 } else
133 d_ready = false;
134 // }
135 }
136}
137
138} /* namespace sysc */