scc  2024.06
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 
33 #include <interfaces/tilelink/pin/tl_uh_bfm.h>
34 #include <scc/report.h>
35 #include <scc/utilities.h>
36 
37 namespace sysc {
38 
39 using namespace sc_core;
40 
41 tl_uh_bfm::tl_uh_bfm(sc_module_name nm, int64_t offset)
42 : sc_module(nm)
43 , offset(offset)
44 , NAMED(socket)
45 , NAMED(clock)
46 , NAMED(reset)
47 , NAMED(a_bits_address)
48 , NAMED(a_bits_data)
49 , NAMED(a_ready)
50 , NAMED(a_valid)
51 , NAMED(a_bits_opcode)
52 , NAMED(a_bits_param)
53 , NAMED(a_bits_size)
54 , NAMED(a_bits_source)
55 , NAMED(a_bits_mask)
56 , NAMED(a_bits_corrupt)
57 , NAMED(d_bits_data)
58 , NAMED(d_ready)
59 , NAMED(d_valid)
60 , NAMED(d_bits_opcode)
61 , NAMED(d_bits_size)
62 , NAMED(d_bits_source)
63 , NAMED(fw_queue) {
64  socket.register_nb_transport_fw(
65  [this](tlm::tlm_generic_payload& gp, tlm::tlm_phase& phase, sc_core::sc_time& delay) -> tlm::tlm_sync_enum {
66  if(phase == tlm::BEGIN_REQ && gp.get_command() != tlm::TLM_IGNORE_COMMAND) {
67  gp.acquire();
68  fw_queue.notify(gp, delay);
69  return tlm::TLM_ACCEPTED;
70  } else if(phase == tlm::END_RESP) {
71  gp.release();
72  d_ready = true;
73  }
74  });
75 
76  SC_METHOD(tl_response_method);
77  sensitive << clock.pos();
78  SC_THREAD(fw_thread);
79 }
80 
81 tl_uh_bfm::~tl_uh_bfm() = default;
82 
83 void tl_uh_bfm::fw_thread() {
84  d_ready = true;
85  while(true) {
86  a_valid = false;
87  wait(fw_queue.get_event());
88  auto gp = fw_queue.get_next_transaction();
89  if(gp->get_data_length() == 4) {
90  auto addr = gp->get_address() + offset;
91  a_bits_address = addr;
92  a_valid = true;
93  a_bits_param = 0;
94  a_bits_size = 2; // 2^2 bytes
95  a_bits_source = 0x55;
96  a_bits_mask = 0xf;
97  a_bits_corrupt = false;
98  if(gp->get_command() == tlm::TLM_WRITE_COMMAND) {
99  a_bits_opcode = PutFullData;
100  a_bits_data = *(uint32_t*)gp->get_data_ptr();
101  } else {
102  a_bits_opcode = Get;
103  a_bits_data = 0;
104  }
105  tl_in_progress.push_back(gp);
106  do {
107  wait(clock.posedge_event());
108  } while(a_ready == false);
109  } else
110  SCCERR("tlbfm") << "Got transaction with unequal length";
111  }
112 }
113 
114 void tl_uh_bfm::tl_response_method() {
115  if(d_valid && d_ready) {
116  // if(d_bits_source==0x55){ // this is ours
117  auto gp = tl_in_progress.front();
118  sc_assert(gp && "Got TL response without a request in queue");
119  tl_in_progress.pop_front();
120  if(gp->get_command() == tlm::TLM_WRITE_COMMAND) {
121  sc_assert(d_bits_opcode == AccessAck && "TL did not respond with AccessAck to write request");
122  } else {
123  sc_assert(d_bits_opcode == AccessAckData && "TL did not respond with AccessAckData to read request");
124  *(uint32_t*)(gp->get_data_ptr()) = d_bits_data;
125  }
126  gp->set_response_status(tlm::TLM_OK_RESPONSE);
127  sc_core::sc_time delay;
128  tlm::tlm_phase phase{tlm::BEGIN_RESP};
129  auto ret = socket->nb_transport_bw(*gp, phase, delay);
130  if(ret == tlm::TLM_COMPLETED || (ret == tlm::TLM_UPDATED && phase == tlm::END_RESP)) {
131  d_ready = true;
132  gp->release();
133  } else
134  d_ready = false;
135  // }
136  }
137 }
138 
139 } /* namespace sysc */