summaryrefslogtreecommitdiff
path: root/util/tlm/examples/master_port/traffic_generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'util/tlm/examples/master_port/traffic_generator.cc')
-rw-r--r--util/tlm/examples/master_port/traffic_generator.cc154
1 files changed, 154 insertions, 0 deletions
diff --git a/util/tlm/examples/master_port/traffic_generator.cc b/util/tlm/examples/master_port/traffic_generator.cc
new file mode 100644
index 000000000..33e94a813
--- /dev/null
+++ b/util/tlm/examples/master_port/traffic_generator.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2016, Dresden University of Technology (TU Dresden)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Christian Menard
+ */
+
+#include "base/random.hh"
+#include "traffic_generator.hh"
+
+TrafficGenerator::TrafficGenerator(sc_core::sc_module_name name)
+ : sc_core::sc_module(name),
+ requestInProgress(0),
+ peq(this, &TrafficGenerator::peq_cb)
+{
+ socket.register_nb_transport_bw(this, &TrafficGenerator::nb_transport_bw);
+ SC_THREAD(process);
+}
+
+void
+TrafficGenerator::process()
+{
+ auto rnd = Random(time(NULL));
+
+ unsigned const memSize = (1 << 10); // 512 MB
+
+ while (true) {
+
+ wait(sc_core::sc_time((double)rnd.random(1,100), sc_core::SC_NS));
+
+ auto trans = mm.allocate();
+ trans->acquire();
+
+ std::string cmdStr;
+ if (rnd.random(0,1)) // Generate a write request?
+ {
+ cmdStr = "write";
+ trans->set_command(tlm::TLM_WRITE_COMMAND);
+ dataBuffer = rnd.random(0,0xffff);
+ } else {
+ cmdStr = "read";
+ trans->set_command(tlm::TLM_READ_COMMAND);
+ }
+
+ trans->set_data_ptr(reinterpret_cast<unsigned char*>(&dataBuffer));
+ trans->set_address(rnd.random(0, (int)(memSize-1)));
+ trans->set_data_length(4);
+ trans->set_streaming_width(4);
+ trans->set_byte_enable_ptr(0);
+ trans->set_dmi_allowed(0);
+ trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
+
+ // honor the BEGIN_REQ/END_REQ exclusion rule
+ if (requestInProgress)
+ sc_core::wait(endRequestEvent);
+
+ std::stringstream ss;
+ ss << "Send " << cmdStr << " request @0x" << std::hex
+ << trans->get_address();
+ SC_REPORT_INFO("Traffic Generator", ss.str().c_str());
+
+ // send the request
+ requestInProgress = trans;
+ tlm::tlm_phase phase = tlm::BEGIN_REQ;
+ auto delay = sc_core::SC_ZERO_TIME;
+
+ auto status = socket->nb_transport_fw(*trans, phase, delay);
+
+ // Check status
+ if (status == tlm::TLM_UPDATED) {
+ peq.notify(*trans, phase, delay);
+ } else if (status == tlm::TLM_COMPLETED) {
+ requestInProgress = 0;
+ checkTransaction(*trans);
+ SC_REPORT_INFO("Traffic Generator", "request completed");
+ trans->release();
+ }
+ }
+}
+
+void
+TrafficGenerator::peq_cb(tlm::tlm_generic_payload& trans,
+ const tlm::tlm_phase& phase)
+{
+ if (phase == tlm::END_REQ ||
+ (&trans == requestInProgress && phase == tlm::BEGIN_RESP)) {
+ // The end of the BEGIN_REQ phase
+ requestInProgress = 0;
+ endRequestEvent.notify();
+ } else if (phase == tlm::BEGIN_REQ || phase == tlm::END_RESP)
+ SC_REPORT_FATAL("TLM-2",
+ "Illegal transaction phase received by initiator");
+
+ if (phase == tlm::BEGIN_RESP) {
+ checkTransaction(trans);
+ SC_REPORT_INFO("Traffic Generator", "received response");
+
+ // Send end response
+ tlm::tlm_phase fw_phase = tlm::END_RESP;
+
+ // stress the retry mechanism by deferring the response
+ auto delay = sc_core::sc_time(5.0, sc_core::SC_NS);
+ socket->nb_transport_fw(trans, fw_phase, delay);
+ trans.release();
+ }
+}
+
+void
+TrafficGenerator::checkTransaction(tlm::tlm_generic_payload& trans)
+{
+ if (trans.is_response_error()) {
+ std::stringstream ss;
+ ss << "Transaction returned with error, response status = %s"
+ << trans.get_response_string();
+ SC_REPORT_ERROR("TLM-2", ss.str().c_str());
+ }
+}
+
+tlm::tlm_sync_enum
+TrafficGenerator::nb_transport_bw(tlm::tlm_generic_payload& trans,
+ tlm::tlm_phase& phase,
+ sc_core::sc_time& delay)
+{
+ trans.acquire();
+ peq.notify(trans, phase, delay);
+ return tlm::TLM_ACCEPTED;
+}