/******************************************************************************* * Copyright (C) 2024 Juan Neyra * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ******************************************************************************/ #include "NetworkInterfaceTlmCS.h" DECLARE_EXTENDED_PHASE(INTERNAL_PROC_PHASE); NetworkInterfaceTlmCS::NetworkInterfaceTlmCS(sc_module_name nm, Node& node, uint8_t max_pos[3]) : NetworkInterfaceTlm(nm, node, max_pos) { initiator_cs.register_nb_transport_bw(this, &NetworkInterfaceTlmCS::nb_transport_bw_cb, 0); target_cs.register_nb_transport_fw(this, &NetworkInterfaceTlmCS::nb_transport_fw_cb, 0); } NetworkInterfaceTlmCS::~NetworkInterfaceTlmCS() { } // Flits are now chunks of data, but in programming, // they can still be treated the same way void NetworkInterfaceTlmCS::send_flit(Packet* p, Flit* f){ tlm_gp* trans = build_transaction(p, f); credit_counter--; sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); tlm::tlm_phase send_phase = tlm::BEGIN_REQ; if(p->dataType == TYPE_STREAM){ initiator_cs->nb_transport_fw(*trans, send_phase, delay); } else{ initiator->nb_transport_fw(*trans, send_phase, delay); } } bool NetworkInterfaceTlmCS::check_cs_needed(tlm_gp& trans){ int type = get_type_from_extension(trans); return type == TYPE_INIT_STREAM || type == TYPE_END_STREAM; }; void NetworkInterfaceTlmCS::send_cs_rout_conf_msg(tlm_gp& trans){ tlm::tlm_generic_payload* new_trans = m_mm.allocate(); new_trans->acquire(); new_trans->set_command(tlm::TLM_WRITE_COMMAND); new_trans->set_address(trans.get_address()); new_trans->set_data_ptr(trans.get_data_ptr()); new_trans->set_data_length(trans.get_data_length()); new_trans->set_streaming_width(trans.get_streaming_width()); new_trans->set_byte_enable_ptr(trans.get_byte_enable_ptr()); new_trans->set_dmi_allowed(false); new_trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); // add id to new_transaction link_extension* ext = new link_extension(); ext->link = dest_link; // set direction of connected router ext->data_type = get_type_from_extension(trans); new_trans->set_extension(ext); // send transaction in socket tlm_phase phase = BEGIN_REQ; sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); initiator_cs->nb_transport_fw(*new_trans, phase, delay); } void NetworkInterfaceTlmCS::receive_and_process_flit(tlm_gp& trans){ trans.set_response_status(tlm::TLM_OK_RESPONSE); unsigned char* data_ptr = trans.get_data_ptr(); Flit* received_flit = reinterpret_cast(data_ptr); Packet* p = received_flit->packet; double time = sc_time_stamp().to_double(); auto position = find(p->inTransmit.begin(), p->inTransmit.end(), received_flit->id); if (position!=p->inTransmit.end()) p->inTransmit.erase(position); p->transmitted.push_back(received_flit->id); // log arrived flit if (received_flit->type==TAIL || received_flit->type==SINGLE){ stringstream ss; string flit_type = received_flit->type==SINGLE ? "Single":"Tail"; ss << "Receive Flit " << flit_type << *received_flit; log_info(ss.str()); } if (!p->toTransmit.empty() || !p->inTransmit.empty()) { stringstream ss; ss << "Received Tail Flit, but still missing flits! " << *received_flit; log_info(ss.str()); } //globalReport.issueNoCOutputDataAmount(sc_time_stamp(),globalResources.bitWidth); if (p->toTransmit.empty() && p->inTransmit.empty()) packet_recv_queue.push(p); credit_counter++; // send configuration message to cs_router if(check_cs_needed(link, trans)){ send_cs_rout_conf_msg(trans); } // send response if not type stream if(p->dataType != TYPE_STREAM){ if(resp_in_progress) { if(nxt_resp_pend){ log_fatal("Attempt to have two pending responses in target"); nxt_resp_pend = &trans; } } else{ send_response(trans); } } } tlm::tlm_sync_enum NetworkInterfaceTlmCS::send_end_req(tlm_gp& trans){ // Queue the acceptance and the response with the appropriate latency tlm::tlm_phase bw_phase = tlm::END_REQ; sc_time delay = sc_time(REQ_END_DELAY, UNITS_DELAY); // Accept delay tlm::tlm_sync_enum status = target->nb_transport_bw(trans, bw_phase, delay); if (status == tlm::TLM_COMPLETED) { trans.release(); return status; } // Queue internal event to mark beginning of response delay = p->dataType != TYPE_STREAM ? delay + sc_time(INTERN_PROC_DELAY, UNITS_DELAY) : SC_ZERO_TIME; // no processing on stream target_peq.notify(trans, INTERNAL_PROC_PHASE, delay); return status; }