From ae0665f69e13689da3c369f47f0463d9932bf2de Mon Sep 17 00:00:00 2001 From: juanmanuel Date: Sun, 6 Oct 2024 09:55:36 -0500 Subject: [PATCH] feat: adding circuit switching routers and NI --- config/simple_2_point_test/2pt_data.xml | 10 +- config/simple_test/simple_data.xml | 10 +- src/networkInterface/NetworkInterfaceTlm.cpp | 69 ++++--- src/networkInterface/NetworkInterfaceTlm.h | 22 ++- .../NetworkInterfaceTlmCS.cpp | 151 +++++++++++++++ src/networkInterface/NetworkInterfaceTlmCS.h | 66 +++++++ src/networkManager/NetworkManager.cpp | 3 +- src/noc/noc.cpp | 24 ++- src/noc/noc.h | 10 +- src/router/router.cpp | 122 +++++++++--- src/router/router.h | 51 ++++- src/router/router_cs.cpp | 174 ++++++++++++++++++ src/router/router_cs.h | 91 +++++++++ src/utils/configuration.h | 7 + 14 files changed, 707 insertions(+), 103 deletions(-) create mode 100755 src/networkInterface/NetworkInterfaceTlmCS.cpp create mode 100755 src/networkInterface/NetworkInterfaceTlmCS.h create mode 100755 src/router/router_cs.cpp create mode 100755 src/router/router_cs.h diff --git a/config/simple_2_point_test/2pt_data.xml b/config/simple_2_point_test/2pt_data.xml index c694991..d06a045 100644 --- a/config/simple_2_point_test/2pt_data.xml +++ b/config/simple_2_point_test/2pt_data.xml @@ -2,16 +2,10 @@ - + - - - - - - - + diff --git a/config/simple_test/simple_data.xml b/config/simple_test/simple_data.xml index 27d0643..aa5f49b 100644 --- a/config/simple_test/simple_data.xml +++ b/config/simple_test/simple_data.xml @@ -2,16 +2,10 @@ - + - - - - - - - + diff --git a/src/networkInterface/NetworkInterfaceTlm.cpp b/src/networkInterface/NetworkInterfaceTlm.cpp index c024b4b..b93d0d1 100755 --- a/src/networkInterface/NetworkInterfaceTlm.cpp +++ b/src/networkInterface/NetworkInterfaceTlm.cpp @@ -123,6 +123,43 @@ void NetworkInterfaceTlm::generateFlitsForPacket(Packet* p) { } } +tlm_gp* NetworkInterfaceTlm::build_transaction(Packet* p, Flit* f){ + // allocate tlm object + tlm_gp* trans = m_mm.allocate(); + trans->acquire(); + // add id to transaction + link_extension* ext = new link_extension(); + ext->link = Direction::local; + ext->data_type = p->dataType; + trans->set_extension(ext); + + trans->set_command(tlm::TLM_WRITE_COMMAND); + + float dst_pos[3] = {p->dst.pos.x, p->dst.pos.y, p->dst.pos.z}; + uint8_t int_dest_pos[3]; + convert_pos_to_int(dst_pos, int_dest_pos); + trans->set_address(int_dest_pos[0] + int_dest_pos[1]*max_pos[0] + + int_dest_pos[2]*max_pos[0]*max_pos[1]); + trans->set_data_ptr(reinterpret_cast(f)); + trans->set_data_length(p->size); + trans->set_streaming_width(4); + trans->set_byte_enable_ptr(0); + trans->set_dmi_allowed(false); + trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + return trans; +} + + +void NetworkInterfaceTlm::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; + initiator->nb_transport_fw(*trans, send_phase, delay); +} + void NetworkInterfaceTlm::send_data_to_noc(){ // if no flits to transmit, generate them Packet* p = packet_send_queue.front(); @@ -144,40 +181,12 @@ void NetworkInterfaceTlm::send_data_to_noc(){ packet_send_queue.pop(); } - // allocate tlm object - tlm::tlm_generic_payload* trans = m_mm.allocate(); - trans->acquire(); - // add id to transaction - link_extension* ext = new link_extension(); - ext->link = Direction::local; - trans->set_extension(ext); - // send flit - trans->set_command(tlm::TLM_WRITE_COMMAND); - - float dst_pos[3] = {p->dst.pos.x, p->dst.pos.y, p->dst.pos.z}; - uint8_t int_dest_pos[3]; - convert_pos_to_int(dst_pos, int_dest_pos); - trans->set_address(int_dest_pos[0] + int_dest_pos[1]*max_pos[0] + - int_dest_pos[2]*max_pos[0]*max_pos[1]); - trans->set_data_ptr(reinterpret_cast - (current_flit)); - trans->set_data_length(p->size); - trans->set_streaming_width(4); - trans->set_byte_enable_ptr(0); - trans->set_dmi_allowed(false); - trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); - - credit_counter--; - - sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); - tlm::tlm_phase send_phase = tlm::BEGIN_REQ; - initiator->nb_transport_fw(*trans, send_phase, delay); + send_flit(p, current_flit); string start_end_pos[2]; get_start_end_pos_string(p, start_end_pos); log_info("Flit send to "+start_end_pos[1]+" from "+start_end_pos[0]); globalReport.issueNoCInputDataAmount(sc_time_stamp(),globalResources.bitWidth); - } @@ -303,7 +312,7 @@ void NetworkInterfaceTlm::receive_and_process_flit(tlm_gp& trans){ << *received_flit; log_info(ss.str()); } - globalReport.issueNoCOutputDataAmount(sc_time_stamp(),globalResources.bitWidth); + //globalReport.issueNoCOutputDataAmount(sc_time_stamp(),globalResources.bitWidth); if (p->toTransmit.empty() && p->inTransmit.empty()) packet_recv_queue.push(p); credit_counter++; diff --git a/src/networkInterface/NetworkInterfaceTlm.h b/src/networkInterface/NetworkInterfaceTlm.h index 2f3924c..be73d17 100755 --- a/src/networkInterface/NetworkInterfaceTlm.h +++ b/src/networkInterface/NetworkInterfaceTlm.h @@ -55,7 +55,7 @@ public: // To PE sc_in clk; PacketPortContainer* packetPortContainer; - // To Router + // To NoC ni_init_socket initiator; ni_targ_socket target; tlm_utils::peq_with_cb_and_phase init_peq; @@ -104,6 +104,24 @@ public: */ void send_data_to_noc(); + /** + * Sends flit to noc + * + * @param p parent packet of the flit to send + * @param f flit to send + */ + void send_flit(Packet* p, Flit* f); + + /** + * Build the transaction tp send. Called by send flit + * + * @param p parent packet of the flit to send + * @param f flit to send + * + * @return created transaction + */ + tlm_gp* build_transaction(Packet* p, Flit* f); + /** * Generates flits when a packet arrives */ @@ -141,7 +159,7 @@ public: void check_transaction(tlm_gp& trans); /** - * Logs the arrival of a flit + * Logs the arrival of a flit. After processing, sends a response * * @param trans TLM transaction object */ diff --git a/src/networkInterface/NetworkInterfaceTlmCS.cpp b/src/networkInterface/NetworkInterfaceTlmCS.cpp new file mode 100755 index 0000000..990f54a --- /dev/null +++ b/src/networkInterface/NetworkInterfaceTlmCS.cpp @@ -0,0 +1,151 @@ +/******************************************************************************* + * 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; +} diff --git a/src/networkInterface/NetworkInterfaceTlmCS.h b/src/networkInterface/NetworkInterfaceTlmCS.h new file mode 100755 index 0000000..5b46756 --- /dev/null +++ b/src/networkInterface/NetworkInterfaceTlmCS.h @@ -0,0 +1,66 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +#pragma once + +#ifndef SC_INCLUDE_DYNAMIC_PROCESSES +#define SC_INCLUDE_DYNAMIC_PROCESSES +#endif + +#include "NetworkInterfaceTlm.h" +#include "utils/memory_manager.h" + +class NetworkInterfaceTlmCS : public NetworkInterfaceTlm { +public: + SC_HAS_PROCESS(NetworkInterfaceTlmCS); + + NetworkInterfaceTlmCS(sc_module_name nm, Node& node, uint8_t max_pos[3]); + + ~NetworkInterfaceTlmCS() override; + + // To Circuit Switching NoC + ni_init_socket initiator_cs; + ni_targ_socket target_cs; + +private: + /** + * Sends flit to packet switching noc or circuit switching noc + * + * @param p parent packet of the flit to send + * @param f flit to send + */ + void send_flit(Packet* p, Flit* f) override; + + /** + * Logs the arrival of a flit. After processing, sends a + * response if needed + * + * @param trans TLM transaction object + */ + void receive_and_process_flit(tlm_gp& trans) override; + + /** + * Send end request + * + * @param trans TLM generic payload object + */ + tlm::tlm_sync_enum send_end_req(tlm_gp& trans) override; +}; diff --git a/src/networkManager/NetworkManager.cpp b/src/networkManager/NetworkManager.cpp index 83e0d5d..9d9bdcf 100755 --- a/src/networkManager/NetworkManager.cpp +++ b/src/networkManager/NetworkManager.cpp @@ -96,7 +96,6 @@ void NetworkManager::createNetworkParticipants() { } - void NetworkManager::createLinks() { int link_id = 0; for (auto &c : globalResources.connections) { @@ -113,7 +112,7 @@ void NetworkManager::createLinks() { NetworkInterfaceTlm* ni = dynamic_cast( networkParticipants.at(ni_id)); - MyRouter* router = tlmNoc->getRouterNodeId(rout_id); + TlmRouter* router = tlmNoc->getRouterNodeId(rout_id); ni->initiator.bind(*router->target_socket[DIR::Local]); router->init_socket[DIR::Local]->bind(ni->target); } diff --git a/src/noc/noc.cpp b/src/noc/noc.cpp index 0737b83..fa7b3bf 100755 --- a/src/noc/noc.cpp +++ b/src/noc/noc.cpp @@ -62,8 +62,7 @@ void TlmNoc::initNoc() { get_max_pos(max_pos); for (Node &n : globalResources.nodes) { - if (n.type->model == "RouterVC") { - string name = "router_" + to_string(n.id); + if (n.type->model == "Router" || n.type->model == "RouterCS"){ float float_rout_pos[3] = {n.pos.x, n.pos.y, n.pos.z}; uint8_t rout_pos[3]; convert_pos_to_int(float_rout_pos, rout_pos); @@ -72,7 +71,15 @@ void TlmNoc::initNoc() { to_string(rout_pos[0]) + "," + to_string(rout_pos[1]) + "," + to_string(rout_pos[2]); log_info(msg); - MyRouter *r = new MyRouter(name.c_str(), rout_pos, max_pos); + TlmRouter *r; + if (n.type->model == "Router") { + string name = "router_" + to_string(n.id); + r = new TlmRouter(name.c_str(), rout_pos, max_pos); + } + else { + string name = "routercs_" + to_string(n.id); + r = new TlmRouterCS(name.c_str(), rout_pos, max_pos); + } routers.push_back(r); int id = routers.size()-1; mapNodeRouter.insert( @@ -85,8 +92,8 @@ void TlmNoc::initNoc() { void TlmNoc::connectRouters(Node node1, Node node2, int link){ int n1_id = mapNodeRouter[node1.id]; int n2_id = mapNodeRouter[node2.id]; - if(node1.type->model == "RouterVC" && - node2.type->model == "RouterVC"){ + if((node1.type->model=="Router" || node1.type->model=="RouterCS") && + (node2.type->model=="Router" || node1.type->model=="RouterCS")){ int connDir = node1.getDirOfCon(link); int opposDir = DIR::getOppositeDir(connDir); @@ -100,7 +107,8 @@ void TlmNoc::connectRouters(Node node1, Node node2, int link){ DIR::toString(connDir), DIR::toString(opposDir)); } else{ - int r_id = node1.type->model == "RouterVC" ? n1_id:n2_id; + int r_id = (node1.type->model == "Router" || + node1.type->model == "RouterCS") ? n1_id:n2_id; api_initiators.push_back(routers[r_id]->init_socket[DIR::Local]); api_targets.push_back(routers[r_id]->target_socket[DIR::Local]); routers[r_id]->valid_links[DIR::Local] = true; @@ -153,11 +161,11 @@ void TlmNoc::connectNoc(){ connectUnbounded(); } -MyRouter* TlmNoc::getRouter(int id){ +TlmRouter* TlmNoc::getRouter(int id){ return routers.at(id); } -MyRouter* TlmNoc::getRouterNodeId(int node_id){ +TlmRouter* TlmNoc::getRouterNodeId(int node_id){ int rout_id = mapNodeRouter.find(node_id)->first; return routers.at(rout_id); } diff --git a/src/noc/noc.h b/src/noc/noc.h index 94e652e..52f6ecd 100755 --- a/src/noc/noc.h +++ b/src/noc/noc.h @@ -42,8 +42,8 @@ using namespace tlm; class TlmNoc : public sc_module { public: - typedef tlm_utils::simple_initiator_socket_tagged tlm_init_socket; - typedef tlm_utils::simple_target_socket_tagged tlm_targ_socket; + typedef tlm_utils::simple_initiator_socket_tagged tlm_init_socket; + typedef tlm_utils::simple_target_socket_tagged tlm_targ_socket; SC_HAS_PROCESS(TlmNoc); @@ -55,11 +55,11 @@ public: std::vector api_targets; uint8_t max_pos[3]; std::map mapNodeRouter; - MyRouter* getRouter(int id); - MyRouter* getRouterNodeId(int node_id); + TlmRouter* getRouter(int id); + TlmRouter* getRouterNodeId(int node_id); private: - std::vector routers; + std::vector routers; uint8_t num_rout_x; uint8_t num_rout_y; uint8_t num_rout_z; diff --git a/src/router/router.cpp b/src/router/router.cpp index ff345b0..d1e60c9 100755 --- a/src/router/router.cpp +++ b/src/router/router.cpp @@ -25,39 +25,36 @@ #include #include "ratatoskrUtils/utils/Structures.h" -DECLARE_EXTENDED_PHASE(INTERNAL_PROC_PHASE); - /* Constructor */ -MyRouter::MyRouter(sc_module_name name, uint8_t rout_pos[3], +TlmRouter::TlmRouter(sc_module_name name, uint8_t rout_pos[3], uint8_t max_pos[3]): sc_module(name), router_name(name), - init_peq(this, &MyRouter::init_peq_cb), - target_peq(this, &MyRouter::target_peq_cb) { + init_peq(this, &TlmRouter::init_peq_cb), + target_peq(this, &TlmRouter::target_peq_cb) { sc_report_handler::set_actions(R_LOG, SC_INFO, SC_LOG|SC_DISPLAY); copy(rout_pos, rout_pos + 3, this->rout_pos); copy(max_pos, max_pos + 3, this->max_pos); initialize(); } -MyRouter::~MyRouter(){ +TlmRouter::~TlmRouter(){ } -void MyRouter::initialize(){ +void TlmRouter::initialize(){ for(int link=0; linkacquire(); new_trans->set_command(tlm::TLM_WRITE_COMMAND); @@ -82,8 +78,15 @@ void MyRouter::send_begin_req(int link, tlm_gp& trans, int dest_link){ // 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); + return new_trans; +} + +void TlmRouter::send_begin_req(int link, tlm_gp& trans, int dest_link){ + tlm_gp* new_trans = build_transaction(trans, dest_link); + // send transaction in socket tlm_phase phase = BEGIN_REQ; sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); @@ -107,11 +110,14 @@ void MyRouter::send_begin_req(int link, tlm_gp& trans, int dest_link){ } -bool MyRouter::send_data(int link, int dest_link, tlm_gp& trans){ +bool TlmRouter::send_data(int link, int dest_link, tlm_gp& trans){ log_info(link,"Send data to link:"+DIR::toString(dest_link)); // check credits or that previous message is complete if (credit_counter[dest_link] > 0 && !curr_req[dest_link]){ send_begin_req(link, trans, dest_link); + if(check_cs_needed(link, trans)){ + send_cs_rout_conf_msg(link, dest_link, trans); + } return true; } else { @@ -123,7 +129,7 @@ bool MyRouter::send_data(int link, int dest_link, tlm_gp& trans){ } } -void MyRouter::check_transaction(int link, tlm_gp& trans) { +void TlmRouter::check_transaction(int link, tlm_gp& trans) { if(trans.is_response_error()) { char txt[100]; sprintf(txt, "Transaction returned with error, response status = %s", @@ -143,22 +149,78 @@ void MyRouter::check_transaction(int link, tlm_gp& trans) { trans.release(); } -int MyRouter::get_link_from_extension(tlm_gp& trans){ +int TlmRouter::get_link_from_extension(tlm_gp& trans){ link_extension* extension; trans.get_extension(extension); return extension->link; } +int TlmRouter::get_type_from_extension(tlm_gp& trans){ + link_extension* extension; + trans.get_extension(extension); + return extension->data_type; +} + +/******************* CS CONFIG FUNCTIONS **********************/ +bool TlmRouter::check_cs_needed(int link, int destination, tlm_gp& trans){ + int type = get_type_from_extension(trans); + return (link != Dir::local || destination != Dir::local) && + (type == TYPE_INIT_STREAM || type == TYPE_END_STREAM); +}; + +void TlmRouter::send_cs_rout_conf_msg(int link, int destination, tlm_gp& trans){ + int dest_link = dir::local; + int* data = new int(link | destination<<2); + + tlm::tlm_generic_payload* conf_trans = m_mm.allocate(); + conf_trans->acquire(); + conf_trans->set_command(tlm::TLM_WRITE_COMMAND); + conf_trans->set_address(rout_pos[0] + rout_pos[1]*max_pos[0] + + rout_pos[2]*max_pos[0]*max_pos[1]); + conf_trans->set_data_ptr(data); + conf_trans->set_data_length(sizeof(int)); + conf_trans->set_streaming_width(4); + conf_trans->set_byte_enable_ptr(0); + conf_trans->set_dmi_allowed(false); + conf_trans->set_response_status(tlm::TLM_INCOMPLETE_RESPONSE); + + // add id to transaction + link_extension* ext = new link_extension(); + ext->link = dest_link; // set direction of connected router + ext->data_type = get_type_from_extension(trans); + conf_trans->set_extension(ext); + + // send transaction in socket + tlm_phase phase = BEGIN_REQ; + sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); + + tlm_sync_enum status; + status = (*init_socket[dest_link])->nb_transport_fw( + *conf_trans, phase, delay); + curr_req[dest_link] = conf_trans; + credit_counter[dest_link]--; + // react to result + if(status == TLM_UPDATED) { + init_peq.notify(*conf_trans, phase, delay); + } + else if(status == TLM_COMPLETED) { + log_error(link, "Request completed prematurely"); + curr_req[dest_link] = 0; + check_transaction(link, *conf_trans); + credit_counter[dest_link]++; + conf_trans->release(); + } +} /******************* INIT SOCKET FUNCTIONS ********************/ -tlm_sync_enum MyRouter::nb_transport_bw_cb(int id, tlm_gp& trans, +tlm_sync_enum TlmRouter::nb_transport_bw_cb(int id, tlm_gp& trans, tlm_phase& phase, sc_time& delay) { log_info(id, "Backward transport callback start"); init_peq.notify(trans, phase, delay); return TLM_ACCEPTED; } -void MyRouter::init_peq_cb(tlm_gp& trans, const tlm_phase& phase){ +void TlmRouter::init_peq_cb(tlm_gp& trans, const tlm_phase& phase){ int link = get_link_from_extension(trans); log_info(link, "Initiator PEQ callback start"); log_info(link, "Phase "+string(phase.get_name())+" received"); @@ -179,7 +241,7 @@ void MyRouter::init_peq_cb(tlm_gp& trans, const tlm_phase& phase){ } -void MyRouter::start_pend_req(int rel_link){ +void TlmRouter::start_pend_req(int rel_link){ // find pending link Direction pending_link = Direction::invalid; for(uint8_t dir=0; dir { int link; + int data_type; virtual tlm_extension_base* clone() const { return new link_extension(*this); } virtual void copy_from(const tlm_extension_base& ext) { link = static_cast(ext).link; + data_type = static_cast(ext).data_type; } }; -class MyRouter : public sc_module{ +class TlmRouter : public sc_module{ public: // TLM - typedef simple_initiator_socket_tagged rout_init_socket; - typedef simple_target_socket_tagged rout_targ_socket; + typedef simple_initiator_socket_tagged rout_init_socket; + typedef simple_target_socket_tagged rout_targ_socket; rout_init_socket* init_socket[NUM_LINKS]; rout_targ_socket* target_socket[NUM_LINKS]; - peq_with_cb_and_phase init_peq; - peq_with_cb_and_phase target_peq; + peq_with_cb_and_phase init_peq; + peq_with_cb_and_phase target_peq; tlm_gp* curr_req[NUM_LINKS]; - tlm_gp* end_req_pend[NUM_LINKS]; tlm_gp* nxt_resp_pend[NUM_LINKS]; tlm_gp* nxt_send_data_pend[NUM_LINKS]; MemoryManager m_mm; @@ -84,10 +86,10 @@ class MyRouter : public sc_module{ uint8_t max_pos[3]; bool valid_links[NUM_LINKS]; - SC_HAS_PROCESS(MyRouter); - MyRouter(sc_module_name name, uint8_t rout_pos[3], + SC_HAS_PROCESS(TlmRouter); + TlmRouter(sc_module_name name, uint8_t rout_pos[3], uint8_t max_pos[3]); - ~MyRouter(); + ~TlmRouter(); private: /** @@ -95,6 +97,16 @@ class MyRouter : public sc_module{ */ void initialize(); + /** + * Build the transaction tp send. Called by send flit + * + * @param trans TLM generic payload object + * @param dest_link destination link to send the data to + * + * @return created transaction + */ + tlm_gp* build_transaction(tlm_gp& trans, int dest_link); + /** * Send data * @@ -114,6 +126,25 @@ class MyRouter : public sc_module{ */ void check_transaction(int link, tlm_gp& trans); + /** + * If message is init streaming, a router_cs needs to be + * configured + * + * @param link active link + * @param destination destination link to transmit transaction + * @param trans TLM generic payload object + */ + bool check_cs_needed(int link, int destination, tlm_gp& trans); + + /** + * Sends router_cs configuration message to local link + * + * @param link active link + * @param destination destination link to transmit transaction + * @param trans TLM generic payload object + */ + bool send_cs_rout_conf_msg(int link, int destination, tlm_gp& trans); + /** * Callback function for non blocking transport backward * diff --git a/src/router/router_cs.cpp b/src/router/router_cs.cpp new file mode 100755 index 0000000..595683e --- /dev/null +++ b/src/router/router_cs.cpp @@ -0,0 +1,174 @@ +/******************************************************************************* + * 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 "router_cs.h" + +TlmRouterCS::TlmRouterCS(sc_module_name name, uint8_t rout_pos[3], + uint8_t max_pos[3]): + TlmRouter(name, rout_pos, max_pos) { +} + +TlmRouterCS::~TlmRouterCS(){ +} + +void TlmRouterCS::initialize(){ + for(int link=0; linknb_transport_fw( + *new_trans, phase, delay); + curr_req[dest_link] = new_trans; + credit_counter[dest_link]--; + // react to result + if(status == TLM_COMPLETED) { + log_error(link, "Request completed prematurely"); + curr_req[dest_link] = 0; + check_transaction(link, *new_trans); + credit_counter[dest_link]++; + new_trans->release(); + } +} + + +void configure_router(tlm_gp& trans){ + // get link and destination + int* data = trans.get_data_ptr(); + int link = data && 3; + int destination = data >> 2; + // set auto router map + set_auto_router_map(link, destination); +} + +/******************* INIT SOCKET FUNCTIONS ********************/ +tlm_sync_enum TlmRouter::nb_transport_bw_cb(int id, tlm_gp& trans, + tlm_phase& phase, sc_time& delay) { + log_info(id, "Backward transport callback start"); + return TLM_ACCEPTED; +} + +/******************* TARGET SOCKET FUNCTIONS ********************/ +void TlmRouterCS::target_peq_cb(tlm_gp& trans, const tlm_phase& phase){ + int link = DIR::getOppositeDir(get_link_from_extension(trans)); + log_info(link, "Target PEQ callback start"); + log_info(link, "Phase "+string(phase.get_name())+" received"); + switch (phase) { + case BEGIN_REQ: + trans.acquire(); + send_end_req(link, trans); + break; + default: + if(phase == INTERNAL_PROC_PHASE){ + switching(link, trans); + } + else if(phase == CONF_ROUT_PHASE){ + configure_router(trans); + } + else{ + log_error(link, + "Illegal transaction phase received by target"); + } + break; + } +} + +tlm_sync_enum TlmRouterCS::send_end_req(int link, tlm_gp& trans){ + log_info(link, "Send end request start"); + // Queue the acceptance and the response with the appropriate latency + sc_time delay = sc_time(REQ_END_DELAY, UNITS_DELAY); + tlm_phase phase = END_REQ; + tlm_sync_enum status = (*target_socket[link])->nb_transport_bw( + trans, phase, delay); + if (status == TLM_COMPLETED) { + log_warn(link,"Request completed, no response to be send"); + trans.release(); + return status; + } + delay = SC_ZERO_TIME; // no processing in circuit switching routers + // Queue internal event to mark beginning of response + int type = get_type_from_extension(trans); + sc_phase phase = (type == TYPE_STREAM) ? INTERNAL_PROC_PHASE : + CONF_ROUT_PHASE; + target_peq.notify(trans, phase, delay); + + return status; +} + +void TlmRouterCS::switching(int link, tlm_gp& trans){ + log_info(link, "Switching start"); + trans.set_response_status(TLM_OK_RESPONSE); + // arbitration and send message to next router + Dir destination = routing(link, trans); + bool data_sent; + if (destination == Dir::num_dirs) { + data_sent = true; + check_transaction(link, trans); + // change to fatal? + log_warn(link, "Routing failed. Message couldn't be delivered"); + } + else{ + data_sent = send_data(link, destination, trans); + } + // validate pending data sent + if (!data_sent) { + log_error(link,"Attempt to have pending data in same destination"); + } +} diff --git a/src/router/router_cs.h b/src/router/router_cs.h new file mode 100755 index 0000000..24a01f7 --- /dev/null +++ b/src/router/router_cs.h @@ -0,0 +1,91 @@ +/******************************************************************************* + * 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. + ******************************************************************************/ +#pragma once + +#ifndef SC_INCLUDE_DYNAMIC_PROCESSES +#define SC_INCLUDE_DYNAMIC_PROCESSES +#endif + +#include +#include +#include "tlm.h" + +using namespace sc_core; +using namespace sc_dt; +using namespace std; +using namespace tlm; +using namespace tlm_utils; + +DECLARE_EXTENDED_PHASE(CONF_ROUT_PHASE); + +class TlmRouterCS : public sc_module, TlmRouter{ + public: + SC_HAS_PROCESS(TlmRouterCS); + TlmRouterCS(sc_module_name name, uint8_t rout_pos[3], + uint8_t max_pos[3]); + ~TlmRouterCS(); + + void set_auto_router_map(int link, Dir dir); + Dir get_auto_router_map(int link); + + private: + Dir auto_rout_map[NUM_LINKS] = {0}; + + /** + * Configure sockets and set initial values of variables + */ + void initialize() override; + + /** + * Routing + * + * @param link active link + * @param trans TLM generic payload object + */ + Dir TlmRouterCS::routing(int link, tlm_gp& trans) override; + + + /** + * Process arrived data: finds destination link and transmit it + * + * @param link active link + * @param trans TLM generic payload object + */ + void switching(int link, tlm_gp& trans); + + /** + * Send end request + * + * @param link active link + * @param trans TLM generic payload object + */ + tlm::tlm_sync_enum send_end_req(int link, tlm_gp& trans) override; + + /** + * Callback target Payload Event Queue (PEQ) + * + * @param trans TLM generic payload object + * @param phase TLM current phase + */ + void target_peq_cb(tlm_gp& trans, const tlm_phase& phase) override; +}; + diff --git a/src/utils/configuration.h b/src/utils/configuration.h index f995cf5..a43f7fe 100755 --- a/src/utils/configuration.h +++ b/src/utils/configuration.h @@ -41,3 +41,10 @@ using namespace sc_dt; // types typedef tlm::tlm_generic_payload tlm_gp; + +// for circuit switching noc +#define NUM_CREDITS_CS 1 +#define TYPE_PACKET 0 +#define TYPE_STREAM 1 +#define TYPE_INIT_STREAM 2 +#define TYPE_END_STREAM 3