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">
<dataTypes>
<dataType id="0">
<name value="dt_0"/>
<name value="Packet"/>
</dataType>
<dataType id="1">
<name value="dt_1"/>
</dataType>
<dataType id="2">
<name value="dt_2"/>
</dataType>
<dataType id="3">
<name value="dt_3"/>
<name value="Streaming"/>
</dataType>
</dataTypes>
<tasks>

View file

@ -2,16 +2,10 @@
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataTypes>
<dataType id="0">
<name value="dt_0"/>
<name value="Packet"/>
</dataType>
<dataType id="1">
<name value="dt_1"/>
</dataType>
<dataType id="2">
<name value="dt_2"/>
</dataType>
<dataType id="3">
<name value="dt_3"/>
<name value="Stream"/>
</dataType>
</dataTypes>
<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(){
// 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<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);
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++;

View file

@ -55,7 +55,7 @@ public:
// To PE
sc_in<bool> clk;
PacketPortContainer* packetPortContainer;
// To Router
// To NoC
ni_init_socket initiator;
ni_targ_socket target;
tlm_utils::peq_with_cb_and_phase<NetworkInterfaceTlm> 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
*/

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() {
int link_id = 0;
for (auto &c : globalResources.connections) {
@ -113,7 +112,7 @@ void NetworkManager::createLinks() {
NetworkInterfaceTlm* ni =
dynamic_cast<NetworkInterfaceTlm *>(
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);
}

View file

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

View file

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

View file

@ -25,39 +25,36 @@
#include <array>
#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; link<NUM_LINKS; link++){
init_socket[link] = new rout_init_socket((router_name+"_"+
to_string(link)+"_init").c_str());
(*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+"_"+
to_string(link)+"_targ").c_str());
(*target_socket[link]).register_nb_transport_fw(this,
&MyRouter::nb_transport_fw_cb, link);
&TlmRouter::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;
@ -66,8 +63,7 @@ void MyRouter::initialize(){
}
/******************* COMMON FUNCTIONS ********************/
void MyRouter::send_begin_req(int link, tlm_gp& trans, int dest_link){
// create new transaction
tlm_gp* TlmRouter::build_transaction(tlm_gp& trans, int dest_link){
tlm::tlm_generic_payload* new_trans = m_mm.allocate();
new_trans->acquire();
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<link_extension>(extension);
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 ********************/
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<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");
tlm_phase fw_phase = END_RESP;
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 ********************/
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){
log_info(id, "Forward transport callback start");
unsigned int len = trans.get_data_length();
@ -226,7 +288,7 @@ tlm_sync_enum MyRouter::nb_transport_fw_cb(int id,
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));
log_info(link, "Target PEQ callback start");
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");
// Queue the acceptance and the response with the appropriate latency
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;
}
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");
resp_in_progress[link] = true;
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");
trans.set_response_status(TLM_OK_RESPONSE);
// 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]){
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();
uint8_t dest_x = 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 ********************/
void MyRouter::log_info(uint8_t link, string msg){
void TlmRouter::log_info(uint8_t link, string msg){
string str_link = DIR::toString(link);
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);
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);
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);
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/peq_with_cb_and_phase.h"
#include "ratatoskrUtils/model/NetworkParticipant.h"
#include "utils/memory_manager.h"
#include "utils/configuration.h"
#include "utils/utils.h"
@ -47,30 +46,33 @@ using namespace tlm_utils;
#define NUM_LINKS Direction::num_dirs
#define MAX_PRIORITY NUM_LINKS - 1
DECLARE_EXTENDED_PHASE(INTERNAL_PROC_PHASE);
// Define an extension for the transactions
// link always point to initiator link of transaction
struct link_extension : tlm_extension<link_extension> {
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<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:
// TLM
typedef simple_initiator_socket_tagged<MyRouter> rout_init_socket;
typedef simple_target_socket_tagged<MyRouter> rout_targ_socket;
typedef simple_initiator_socket_tagged<TlmRouter> rout_init_socket;
typedef simple_target_socket_tagged<TlmRouter> rout_targ_socket;
rout_init_socket* init_socket[NUM_LINKS];
rout_targ_socket* target_socket[NUM_LINKS];
peq_with_cb_and_phase<MyRouter> init_peq;
peq_with_cb_and_phase<MyRouter> target_peq;
peq_with_cb_and_phase<TlmRouter> init_peq;
peq_with_cb_and_phase<TlmRouter> 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
*

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
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