tlm_noc_sim/src/router/router_cs.cpp

179 lines
6.6 KiB
C++
Raw Normal View History

/*******************************************************************************
* 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"
2024-10-07 17:53:56 +02:00
#include "ratatoskrUtils/utils/Structures.h"
#include "traffic/PacketCS.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(){
TlmRouter::initialize();
cout<<"Inherited function called";
for(int link=0; link<NUM_LINKS; link++){
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];
}
2024-10-07 17:53:56 +02:00
void TlmRouterCS::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]--;
log_info(link, trans,
"credits value updated: " + to_string(credit_counter[link]));
// react to result
if(status == TLM_COMPLETED) {
log_error(link, trans, "Request completed prematurely");
curr_req[dest_link] = 0;
check_transaction(link, *new_trans);
credit_counter[dest_link]++;
log_info(link, trans,
"credits value updated: " + to_string(credit_counter[dest_link]));
new_trans->release();
}
}
void TlmRouterCS::configure_router(int link, tlm_gp& trans){
log_info(link, trans, "Configure router");
// get link and destination
unsigned char* data_ptr = trans.get_data_ptr();
Flit* rec_flit = reinterpret_cast<Flit*>(data_ptr);
PacketCS* rec_packet = reinterpret_cast<PacketCS*>(rec_flit->packet);
int config_link = rec_packet->msg.config_link;
int destination = rec_packet->msg.dest_link;
// set auto router map
log_info(link, trans, "Set auto route of link "+DIR::toString(config_link)
+ " to "+DIR::toString(destination));
set_auto_router_map(config_link, Dir(destination));
}
/******************* INIT SOCKET FUNCTIONS ********************/
2024-10-07 17:53:56 +02:00
tlm_sync_enum TlmRouterCS::nb_transport_bw_cb(int id, tlm_gp& trans,
tlm_phase& phase, sc_time& delay) {
log_info(id, trans, "Backward transport callback start CS");
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, trans, "Target PEQ callback start CS");
log_info(link, trans, "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(link, trans);
}
else{
log_error(link, trans,
"Illegal transaction phase received by target");
}
break;
}
}
tlm_sync_enum TlmRouterCS::send_end_req(int link, tlm_gp& trans){
log_info(link, trans, "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, trans, "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
2024-11-03 20:49:30 +01:00
string type_name = get_type_name(get_type_from_extension(trans));
phase = (type_name == TYPE_STREAM) ? INTERNAL_PROC_PHASE :
CONF_ROUT_PHASE;
2024-11-03 20:49:30 +01:00
log_info(link, trans, "Type of processed message: " + type_name);
target_peq.notify(trans, phase, delay);
return status;
}
void TlmRouterCS::switching(int link, tlm_gp& trans){
log_info(link, trans, "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, trans, "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, trans,
"Attempt to have pending data in same destination");
}
}
int TlmRouterCS::get_type_from_extension(tlm_gp& trans){
link_extension* extension;
trans.get_extension<link_extension>(extension);
return extension->data_type;
}