feat: adding circuit switching routers and NI

This commit is contained in:
juanmanuel 2024-10-06 09:55:36 -05:00
parent 2785db31d2
commit ae0665f69e
14 changed files with 707 additions and 103 deletions

View file

@ -2,16 +2,10 @@
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataTypes> <dataTypes>
<dataType id="0"> <dataType id="0">
<name value="dt_0"/> <name value="Packet"/>
</dataType> </dataType>
<dataType id="1"> <dataType id="1">
<name value="dt_1"/> <name value="Streaming"/>
</dataType>
<dataType id="2">
<name value="dt_2"/>
</dataType>
<dataType id="3">
<name value="dt_3"/>
</dataType> </dataType>
</dataTypes> </dataTypes>
<tasks> <tasks>

View file

@ -2,16 +2,10 @@
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataTypes> <dataTypes>
<dataType id="0"> <dataType id="0">
<name value="dt_0"/> <name value="Packet"/>
</dataType> </dataType>
<dataType id="1"> <dataType id="1">
<name value="dt_1"/> <name value="Stream"/>
</dataType>
<dataType id="2">
<name value="dt_2"/>
</dataType>
<dataType id="3">
<name value="dt_3"/>
</dataType> </dataType>
</dataTypes> </dataTypes>
<tasks> <tasks>

View file

@ -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<unsigned char*>(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(){ void NetworkInterfaceTlm::send_data_to_noc(){
// if no flits to transmit, generate them // if no flits to transmit, generate them
Packet* p = packet_send_queue.front(); Packet* p = packet_send_queue.front();
@ -144,40 +181,12 @@ void NetworkInterfaceTlm::send_data_to_noc(){
packet_send_queue.pop(); packet_send_queue.pop();
} }
// allocate tlm object send_flit(p, current_flit);
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<unsigned char*>
(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);
string start_end_pos[2]; string start_end_pos[2];
get_start_end_pos_string(p, start_end_pos); get_start_end_pos_string(p, start_end_pos);
log_info("Flit send to "+start_end_pos[1]+" from "+start_end_pos[0]); log_info("Flit send to "+start_end_pos[1]+" from "+start_end_pos[0]);
globalReport.issueNoCInputDataAmount(sc_time_stamp(),globalResources.bitWidth); globalReport.issueNoCInputDataAmount(sc_time_stamp(),globalResources.bitWidth);
} }
@ -303,7 +312,7 @@ void NetworkInterfaceTlm::receive_and_process_flit(tlm_gp& trans){
<< *received_flit; << *received_flit;
log_info(ss.str()); 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()) if (p->toTransmit.empty() && p->inTransmit.empty())
packet_recv_queue.push(p); packet_recv_queue.push(p);
credit_counter++; credit_counter++;

View file

@ -55,7 +55,7 @@ public:
// To PE // To PE
sc_in<bool> clk; sc_in<bool> clk;
PacketPortContainer* packetPortContainer; PacketPortContainer* packetPortContainer;
// To Router // To NoC
ni_init_socket initiator; ni_init_socket initiator;
ni_targ_socket target; ni_targ_socket target;
tlm_utils::peq_with_cb_and_phase<NetworkInterfaceTlm> init_peq; tlm_utils::peq_with_cb_and_phase<NetworkInterfaceTlm> init_peq;
@ -104,6 +104,24 @@ public:
*/ */
void send_data_to_noc(); 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 * Generates flits when a packet arrives
*/ */
@ -141,7 +159,7 @@ public:
void check_transaction(tlm_gp& trans); 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 * @param trans TLM transaction object
*/ */

View file

@ -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<Flit*>(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;
}

View file

@ -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;
};

View file

@ -96,7 +96,6 @@ void NetworkManager::createNetworkParticipants() {
} }
void NetworkManager::createLinks() { void NetworkManager::createLinks() {
int link_id = 0; int link_id = 0;
for (auto &c : globalResources.connections) { for (auto &c : globalResources.connections) {
@ -113,7 +112,7 @@ void NetworkManager::createLinks() {
NetworkInterfaceTlm* ni = NetworkInterfaceTlm* ni =
dynamic_cast<NetworkInterfaceTlm *>( dynamic_cast<NetworkInterfaceTlm *>(
networkParticipants.at(ni_id)); networkParticipants.at(ni_id));
MyRouter* router = tlmNoc->getRouterNodeId(rout_id); TlmRouter* router = tlmNoc->getRouterNodeId(rout_id);
ni->initiator.bind(*router->target_socket[DIR::Local]); ni->initiator.bind(*router->target_socket[DIR::Local]);
router->init_socket[DIR::Local]->bind(ni->target); router->init_socket[DIR::Local]->bind(ni->target);
} }

View file

@ -62,8 +62,7 @@ void TlmNoc::initNoc() {
get_max_pos(max_pos); get_max_pos(max_pos);
for (Node &n : globalResources.nodes) { for (Node &n : globalResources.nodes) {
if (n.type->model == "RouterVC") { if (n.type->model == "Router" || n.type->model == "RouterCS"){
string name = "router_" + to_string(n.id);
float float_rout_pos[3] = {n.pos.x, n.pos.y, n.pos.z}; float float_rout_pos[3] = {n.pos.x, n.pos.y, n.pos.z};
uint8_t rout_pos[3]; uint8_t rout_pos[3];
convert_pos_to_int(float_rout_pos, rout_pos); 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[0]) + "," + to_string(rout_pos[1]) +
"," + to_string(rout_pos[2]); "," + to_string(rout_pos[2]);
log_info(msg); 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); routers.push_back(r);
int id = routers.size()-1; int id = routers.size()-1;
mapNodeRouter.insert( mapNodeRouter.insert(
@ -85,8 +92,8 @@ void TlmNoc::initNoc() {
void TlmNoc::connectRouters(Node node1, Node node2, int link){ void TlmNoc::connectRouters(Node node1, Node node2, int link){
int n1_id = mapNodeRouter[node1.id]; int n1_id = mapNodeRouter[node1.id];
int n2_id = mapNodeRouter[node2.id]; int n2_id = mapNodeRouter[node2.id];
if(node1.type->model == "RouterVC" && if((node1.type->model=="Router" || node1.type->model=="RouterCS") &&
node2.type->model == "RouterVC"){ (node2.type->model=="Router" || node1.type->model=="RouterCS")){
int connDir = node1.getDirOfCon(link); int connDir = node1.getDirOfCon(link);
int opposDir = DIR::getOppositeDir(connDir); int opposDir = DIR::getOppositeDir(connDir);
@ -100,7 +107,8 @@ void TlmNoc::connectRouters(Node node1, Node node2, int link){
DIR::toString(connDir), DIR::toString(opposDir)); DIR::toString(connDir), DIR::toString(opposDir));
} }
else{ 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_initiators.push_back(routers[r_id]->init_socket[DIR::Local]);
api_targets.push_back(routers[r_id]->target_socket[DIR::Local]); api_targets.push_back(routers[r_id]->target_socket[DIR::Local]);
routers[r_id]->valid_links[DIR::Local] = true; routers[r_id]->valid_links[DIR::Local] = true;
@ -153,11 +161,11 @@ void TlmNoc::connectNoc(){
connectUnbounded(); connectUnbounded();
} }
MyRouter* TlmNoc::getRouter(int id){ TlmRouter* TlmNoc::getRouter(int id){
return routers.at(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; int rout_id = mapNodeRouter.find(node_id)->first;
return routers.at(rout_id); return routers.at(rout_id);
} }

View file

@ -42,8 +42,8 @@ using namespace tlm;
class TlmNoc : public sc_module { class TlmNoc : public sc_module {
public: public:
typedef tlm_utils::simple_initiator_socket_tagged<MyRouter> tlm_init_socket; typedef tlm_utils::simple_initiator_socket_tagged<TlmRouter> tlm_init_socket;
typedef tlm_utils::simple_target_socket_tagged<MyRouter> tlm_targ_socket; typedef tlm_utils::simple_target_socket_tagged<TlmRouter> tlm_targ_socket;
SC_HAS_PROCESS(TlmNoc); SC_HAS_PROCESS(TlmNoc);
@ -55,11 +55,11 @@ public:
std::vector<tlm_targ_socket*> api_targets; std::vector<tlm_targ_socket*> api_targets;
uint8_t max_pos[3]; uint8_t max_pos[3];
std::map<int, int> mapNodeRouter; std::map<int, int> mapNodeRouter;
MyRouter* getRouter(int id); TlmRouter* getRouter(int id);
MyRouter* getRouterNodeId(int node_id); TlmRouter* getRouterNodeId(int node_id);
private: private:
std::vector<MyRouter*> routers; std::vector<TlmRouter*> routers;
uint8_t num_rout_x; uint8_t num_rout_x;
uint8_t num_rout_y; uint8_t num_rout_y;
uint8_t num_rout_z; uint8_t num_rout_z;

View file

@ -25,39 +25,36 @@
#include <array> #include <array>
#include "ratatoskrUtils/utils/Structures.h" #include "ratatoskrUtils/utils/Structures.h"
DECLARE_EXTENDED_PHASE(INTERNAL_PROC_PHASE);
/* Constructor */ /* 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]): uint8_t max_pos[3]):
sc_module(name), router_name(name), sc_module(name), router_name(name),
init_peq(this, &MyRouter::init_peq_cb), init_peq(this, &TlmRouter::init_peq_cb),
target_peq(this, &MyRouter::target_peq_cb) { target_peq(this, &TlmRouter::target_peq_cb) {
sc_report_handler::set_actions(R_LOG, SC_INFO, SC_LOG|SC_DISPLAY); sc_report_handler::set_actions(R_LOG, SC_INFO, SC_LOG|SC_DISPLAY);
copy(rout_pos, rout_pos + 3, this->rout_pos); copy(rout_pos, rout_pos + 3, this->rout_pos);
copy(max_pos, max_pos + 3, this->max_pos); copy(max_pos, max_pos + 3, this->max_pos);
initialize(); initialize();
} }
MyRouter::~MyRouter(){ TlmRouter::~TlmRouter(){
} }
void MyRouter::initialize(){ void TlmRouter::initialize(){
for(int link=0; link<NUM_LINKS; link++){ for(int link=0; link<NUM_LINKS; link++){
init_socket[link] = new rout_init_socket((router_name+"_"+ init_socket[link] = new rout_init_socket((router_name+"_"+
to_string(link)+"_init").c_str()); to_string(link)+"_init").c_str());
(*init_socket[link]).register_nb_transport_bw(this, (*init_socket[link]).register_nb_transport_bw(this,
&MyRouter::nb_transport_bw_cb, link); &TlmRouter::nb_transport_bw_cb, link);
target_socket[link] = new rout_targ_socket((router_name+"_"+ target_socket[link] = new rout_targ_socket((router_name+"_"+
to_string(link)+"_targ").c_str()); to_string(link)+"_targ").c_str());
(*target_socket[link]).register_nb_transport_fw(this, (*target_socket[link]).register_nb_transport_fw(this,
&MyRouter::nb_transport_fw_cb, link); &TlmRouter::nb_transport_fw_cb, link);
valid_links[link] = false; valid_links[link] = false;
resp_in_progress[link] = false; resp_in_progress[link] = false;
nxt_resp_pend[link] = 0; nxt_resp_pend[link] = 0;
end_req_pend[link] = 0;
nxt_send_data_pend[link] = 0; nxt_send_data_pend[link] = 0;
curr_req[link] = 0; curr_req[link] = 0;
send_data_in_prog_dest[link] = Direction::invalid; send_data_in_prog_dest[link] = Direction::invalid;
@ -66,8 +63,7 @@ void MyRouter::initialize(){
} }
/******************* COMMON FUNCTIONS ********************/ /******************* COMMON FUNCTIONS ********************/
void MyRouter::send_begin_req(int link, tlm_gp& trans, int dest_link){ tlm_gp* TlmRouter::build_transaction(tlm_gp& trans, int dest_link){
// create new transaction
tlm::tlm_generic_payload* new_trans = m_mm.allocate(); tlm::tlm_generic_payload* new_trans = m_mm.allocate();
new_trans->acquire(); new_trans->acquire();
new_trans->set_command(tlm::TLM_WRITE_COMMAND); 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 // add id to new_transaction
link_extension* ext = new link_extension(); link_extension* ext = new link_extension();
ext->link = dest_link; // set direction of connected router ext->link = dest_link; // set direction of connected router
ext->data_type = get_type_from_extension(trans);
new_trans->set_extension(ext); 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 // send transaction in socket
tlm_phase phase = BEGIN_REQ; tlm_phase phase = BEGIN_REQ;
sc_time delay = sc_time(REQ_INIT_DELAY, UNITS_DELAY); 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)); log_info(link,"Send data to link:"+DIR::toString(dest_link));
// check credits or that previous message is complete // check credits or that previous message is complete
if (credit_counter[dest_link] > 0 && !curr_req[dest_link]){ if (credit_counter[dest_link] > 0 && !curr_req[dest_link]){
send_begin_req(link, trans, 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; return true;
} }
else { 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()) { if(trans.is_response_error()) {
char txt[100]; char txt[100];
sprintf(txt, "Transaction returned with error, response status = %s", sprintf(txt, "Transaction returned with error, response status = %s",
@ -143,22 +149,78 @@ void MyRouter::check_transaction(int link, tlm_gp& trans) {
trans.release(); trans.release();
} }
int MyRouter::get_link_from_extension(tlm_gp& trans){ int TlmRouter::get_link_from_extension(tlm_gp& trans){
link_extension* extension; link_extension* extension;
trans.get_extension<link_extension>(extension); trans.get_extension<link_extension>(extension);
return extension->link; return extension->link;
} }
int TlmRouter::get_type_from_extension(tlm_gp& trans){
link_extension* extension;
trans.get_extension<link_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 ********************/ /******************* 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) { tlm_phase& phase, sc_time& delay) {
log_info(id, "Backward transport callback start"); log_info(id, "Backward transport callback start");
init_peq.notify(trans, phase, delay); init_peq.notify(trans, phase, delay);
return TLM_ACCEPTED; 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); int link = get_link_from_extension(trans);
log_info(link, "Initiator PEQ callback start"); log_info(link, "Initiator PEQ callback start");
log_info(link, "Phase "+string(phase.get_name())+" received"); 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 // find pending link
Direction pending_link = Direction::invalid; Direction pending_link = Direction::invalid;
for(uint8_t dir=0; dir<Direction::num_dirs; dir++){ for(uint8_t dir=0; dir<Direction::num_dirs; dir++){
@ -199,7 +261,7 @@ void MyRouter::start_pend_req(int rel_link){
} }
} }
void MyRouter::send_end_response(int link, tlm_gp& trans){ void TlmRouter::send_end_response(int link, tlm_gp& trans){
log_info(link, "Send end response start"); log_info(link, "Send end response start");
tlm_phase fw_phase = END_RESP; tlm_phase fw_phase = END_RESP;
sc_time delay = sc_time(RESP_END_DELAY, UNITS_DELAY); sc_time delay = sc_time(RESP_END_DELAY, UNITS_DELAY);
@ -208,7 +270,7 @@ void MyRouter::send_end_response(int link, tlm_gp& trans){
/******************* TARGET SOCKET FUNCTIONS ********************/ /******************* TARGET SOCKET FUNCTIONS ********************/
tlm_sync_enum MyRouter::nb_transport_fw_cb(int id, tlm_sync_enum TlmRouter::nb_transport_fw_cb(int id,
tlm_gp& trans, tlm_phase& phase, sc_time& delay){ tlm_gp& trans, tlm_phase& phase, sc_time& delay){
log_info(id, "Forward transport callback start"); log_info(id, "Forward transport callback start");
unsigned int len = trans.get_data_length(); unsigned int len = trans.get_data_length();
@ -226,7 +288,7 @@ tlm_sync_enum MyRouter::nb_transport_fw_cb(int id,
return TLM_ACCEPTED; return TLM_ACCEPTED;
} }
void MyRouter::target_peq_cb(tlm_gp& trans, const tlm_phase& phase){ void TlmRouter::target_peq_cb(tlm_gp& trans, const tlm_phase& phase){
int link = DIR::getOppositeDir(get_link_from_extension(trans)); int link = DIR::getOppositeDir(get_link_from_extension(trans));
log_info(link, "Target PEQ callback start"); log_info(link, "Target PEQ callback start");
log_info(link, "Phase "+string(phase.get_name())+" received"); log_info(link, "Phase "+string(phase.get_name())+" received");
@ -260,7 +322,7 @@ void MyRouter::target_peq_cb(tlm_gp& trans, const tlm_phase& phase){
} }
} }
tlm_sync_enum MyRouter::send_end_req(int link, tlm_gp& trans){ tlm_sync_enum TlmRouter::send_end_req(int link, tlm_gp& trans){
log_info(link, "Send end request start"); log_info(link, "Send end request start");
// Queue the acceptance and the response with the appropriate latency // Queue the acceptance and the response with the appropriate latency
sc_time delay = sc_time(REQ_END_DELAY, UNITS_DELAY); sc_time delay = sc_time(REQ_END_DELAY, UNITS_DELAY);
@ -280,7 +342,7 @@ tlm_sync_enum MyRouter::send_end_req(int link, tlm_gp& trans){
return status; return status;
} }
void MyRouter::send_begin_response(int link, tlm_gp& trans){ void TlmRouter::send_begin_response(int link, tlm_gp& trans){
log_info(link, "Send begin response start"); log_info(link, "Send begin response start");
resp_in_progress[link] = true; resp_in_progress[link] = true;
tlm_phase phase = BEGIN_RESP; tlm_phase phase = BEGIN_RESP;
@ -297,7 +359,7 @@ void MyRouter::send_begin_response(int link, tlm_gp& trans){
} }
} }
void MyRouter::switching(int link, tlm_gp& trans){ void TlmRouter::switching(int link, tlm_gp& trans){
log_info(link, "Switching start"); log_info(link, "Switching start");
trans.set_response_status(TLM_OK_RESPONSE); trans.set_response_status(TLM_OK_RESPONSE);
// arbitration and send message to next router // arbitration and send message to next router
@ -333,7 +395,7 @@ void MyRouter::switching(int link, tlm_gp& trans){
} }
Dir MyRouter::xyz_routing(int link, uint8_t dest[3]){ Dir TlmRouter::xyz_routing(int link, uint8_t dest[3]){
if (dest[0] < rout_pos[0] && valid_links[Dir::west]){ if (dest[0] < rout_pos[0] && valid_links[Dir::west]){
return Dir::west; return Dir::west;
} }
@ -361,7 +423,7 @@ Dir MyRouter::xyz_routing(int link, uint8_t dest[3]){
} }
} }
Dir MyRouter::routing(int link, tlm_gp& trans){ Dir TlmRouter::routing(int link, tlm_gp& trans){
int address = trans.get_address(); int address = trans.get_address();
uint8_t dest_x = address % max_pos[0]; uint8_t dest_x = address % max_pos[0];
uint8_t dest_y = address / max_pos[0]; uint8_t dest_y = address / max_pos[0];
@ -372,22 +434,22 @@ Dir MyRouter::routing(int link, tlm_gp& trans){
/******************* LOG FUNCTIONS ********************/ /******************* LOG FUNCTIONS ********************/
void MyRouter::log_info(uint8_t link, string msg){ void TlmRouter::log_info(uint8_t link, string msg){
string str_link = DIR::toString(link); string str_link = DIR::toString(link);
SC_REPORT_INFO(R_LOG, (router_name+":"+str_link+":"+msg).c_str()); SC_REPORT_INFO(R_LOG, (router_name+":"+str_link+":"+msg).c_str());
} }
void MyRouter::log_warn(uint8_t link, string msg){ void TlmRouter::log_warn(uint8_t link, string msg){
string str_link = DIR::toString(link); string str_link = DIR::toString(link);
SC_REPORT_WARNING(R_LOG, (router_name+":"+str_link+":"+msg).c_str()); SC_REPORT_WARNING(R_LOG, (router_name+":"+str_link+":"+msg).c_str());
} }
void MyRouter::log_error(uint8_t link, string msg){ void TlmRouter::log_error(uint8_t link, string msg){
string str_link = DIR::toString(link); string str_link = DIR::toString(link);
SC_REPORT_ERROR(R_LOG, (router_name+":"+str_link+":"+msg).c_str()); SC_REPORT_ERROR(R_LOG, (router_name+":"+str_link+":"+msg).c_str());
} }
void MyRouter::log_fatal(uint8_t link, string msg){ void TlmRouter::log_fatal(uint8_t link, string msg){
string str_link = DIR::toString(link); string str_link = DIR::toString(link);
SC_REPORT_FATAL(R_LOG, (router_name+":"+str_link+":"+msg).c_str()); SC_REPORT_FATAL(R_LOG, (router_name+":"+str_link+":"+msg).c_str());
} }

View file

@ -32,7 +32,6 @@
#include "tlm_utils/simple_target_socket.h" #include "tlm_utils/simple_target_socket.h"
#include "tlm_utils/peq_with_cb_and_phase.h" #include "tlm_utils/peq_with_cb_and_phase.h"
#include "ratatoskrUtils/model/NetworkParticipant.h"
#include "utils/memory_manager.h" #include "utils/memory_manager.h"
#include "utils/configuration.h" #include "utils/configuration.h"
#include "utils/utils.h" #include "utils/utils.h"
@ -47,30 +46,33 @@ using namespace tlm_utils;
#define NUM_LINKS Direction::num_dirs #define NUM_LINKS Direction::num_dirs
#define MAX_PRIORITY NUM_LINKS - 1 #define MAX_PRIORITY NUM_LINKS - 1
DECLARE_EXTENDED_PHASE(INTERNAL_PROC_PHASE);
// Define an extension for the transactions // Define an extension for the transactions
// link always point to initiator link of transaction // link always point to initiator link of transaction
struct link_extension : tlm_extension<link_extension> { struct link_extension : tlm_extension<link_extension> {
int link; int link;
int data_type;
virtual tlm_extension_base* clone() const { virtual tlm_extension_base* clone() const {
return new link_extension(*this); return new link_extension(*this);
} }
virtual void copy_from(const tlm_extension_base& ext) { virtual void copy_from(const tlm_extension_base& ext) {
link = static_cast<const link_extension&>(ext).link; link = static_cast<const link_extension&>(ext).link;
data_type = static_cast<const link_extension&>(ext).data_type;
} }
}; };
class MyRouter : public sc_module{ class TlmRouter : public sc_module{
public: public:
// TLM // TLM
typedef simple_initiator_socket_tagged<MyRouter> rout_init_socket; typedef simple_initiator_socket_tagged<TlmRouter> rout_init_socket;
typedef simple_target_socket_tagged<MyRouter> rout_targ_socket; typedef simple_target_socket_tagged<TlmRouter> rout_targ_socket;
rout_init_socket* init_socket[NUM_LINKS]; rout_init_socket* init_socket[NUM_LINKS];
rout_targ_socket* target_socket[NUM_LINKS]; rout_targ_socket* target_socket[NUM_LINKS];
peq_with_cb_and_phase<MyRouter> init_peq; peq_with_cb_and_phase<TlmRouter> init_peq;
peq_with_cb_and_phase<MyRouter> target_peq; peq_with_cb_and_phase<TlmRouter> target_peq;
tlm_gp* curr_req[NUM_LINKS]; tlm_gp* curr_req[NUM_LINKS];
tlm_gp* end_req_pend[NUM_LINKS];
tlm_gp* nxt_resp_pend[NUM_LINKS]; tlm_gp* nxt_resp_pend[NUM_LINKS];
tlm_gp* nxt_send_data_pend[NUM_LINKS]; tlm_gp* nxt_send_data_pend[NUM_LINKS];
MemoryManager m_mm; MemoryManager m_mm;
@ -84,10 +86,10 @@ class MyRouter : public sc_module{
uint8_t max_pos[3]; uint8_t max_pos[3];
bool valid_links[NUM_LINKS]; bool valid_links[NUM_LINKS];
SC_HAS_PROCESS(MyRouter); SC_HAS_PROCESS(TlmRouter);
MyRouter(sc_module_name name, uint8_t rout_pos[3], TlmRouter(sc_module_name name, uint8_t rout_pos[3],
uint8_t max_pos[3]); uint8_t max_pos[3]);
~MyRouter(); ~TlmRouter();
private: private:
/** /**
@ -95,6 +97,16 @@ class MyRouter : public sc_module{
*/ */
void initialize(); 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 * Send data
* *
@ -114,6 +126,25 @@ class MyRouter : public sc_module{
*/ */
void check_transaction(int link, tlm_gp& trans); 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 * Callback function for non blocking transport backward
* *

174
src/router/router_cs.cpp Executable file
View file

@ -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; link<NUM_LINKS; link++){
init_socket[link] = new rout_init_socket(("csnoc_"+router_name+
"_"+to_string(link)+"_init").c_str());
(*init_socket[link]).register_nb_transport_bw(this,
&TlmRouterCS::nb_transport_bw_cb, link);
target_socket[link] = new rout_targ_socket(("csnoc_"+router_name+
"_"+to_string(link)+"_targ").c_str());
(*target_socket[link]).register_nb_transport_fw(this,
&TlmRouterCS::nb_transport_fw_cb, link);
valid_links[link] = false;
//resp_in_progress[link] = false;
//nxt_resp_pend[link] = 0;
end_req_pend[link] = 0;
nxt_send_data_pend[link] = 0;
curr_req[link] = 0;
//send_data_in_prog_dest[link] = Direction::invalid;
credit_counter[link] = NUM_CREDITS_CS;
auto_rout_map[link] = Direction::invalid;
}
}
Dir TlmRouterCS::routing(int link, tlm_gp& trans){
return auto_rout_map[link];
}
void TlmRouterCS::set_auto_router_map(int link, Dir dir){
auto_rout_map[link] = dir;
}
Dir TlmRouterCS::get_auto_router_map(int link){
return auto_rout_map[link];
}
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);
tlm_sync_enum status;
status = (*init_socket[dest_link])->nb_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");
}
}

91
src/router/router_cs.h Executable file
View file

@ -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 <systemc>
#include <string>
#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;
};

View file

@ -41,3 +41,10 @@ using namespace sc_dt;
// types // types
typedef tlm::tlm_generic_payload tlm_gp; 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