2024-10-06 16:55:36 +02:00
|
|
|
/*******************************************************************************
|
|
|
|
* 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"
|
2024-10-06 16:55:36 +02:00
|
|
|
|
2024-10-07 22:15:03 +02:00
|
|
|
typedef simple_initiator_socket_tagged<TlmRouter> rout_init_socket;
|
|
|
|
typedef simple_target_socket_tagged<TlmRouter> rout_targ_socket;
|
|
|
|
|
2024-10-06 16:55:36 +02:00
|
|
|
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++){
|
2024-10-07 22:15:03 +02:00
|
|
|
init_socket_cs[link] = new routcs_init_socket(("csnoc_"+router_name+
|
2024-10-06 16:55:36 +02:00
|
|
|
"_"+to_string(link)+"_init").c_str());
|
2024-10-07 22:15:03 +02:00
|
|
|
(*init_socket_cs[link]).register_nb_transport_bw(this,
|
2024-10-06 16:55:36 +02:00
|
|
|
&TlmRouterCS::nb_transport_bw_cb, link);
|
2024-10-07 22:15:03 +02:00
|
|
|
|
|
|
|
target_socket_cs[link] = new routcs_targ_socket(("csnoc_"+router_name+
|
2024-10-06 16:55:36 +02:00
|
|
|
"_"+to_string(link)+"_targ").c_str());
|
2024-10-07 22:15:03 +02:00
|
|
|
(*target_socket_cs[link]).register_nb_transport_fw(this,
|
2024-10-06 16:55:36 +02:00
|
|
|
&TlmRouterCS::nb_transport_fw_cb, link);
|
|
|
|
|
|
|
|
valid_links[link] = false;
|
|
|
|
//resp_in_progress[link] = false;
|
|
|
|
//nxt_resp_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];
|
|
|
|
}
|
|
|
|
|
2024-10-07 17:53:56 +02:00
|
|
|
void TlmRouterCS::send_begin_req(int link, tlm_gp& trans, int dest_link){
|
2024-10-06 16:55:36 +02:00
|
|
|
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;
|
2024-10-07 22:15:03 +02:00
|
|
|
status = (*init_socket_cs[dest_link])->nb_transport_fw(
|
2024-10-06 16:55:36 +02:00
|
|
|
*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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-10-07 17:53:56 +02:00
|
|
|
void TlmRouterCS::configure_router(tlm_gp& trans){
|
2024-10-06 16:55:36 +02:00
|
|
|
// get link and destination
|
2024-10-07 17:53:56 +02:00
|
|
|
unsigned char* data = trans.get_data_ptr();
|
|
|
|
int link = *data && 3;
|
|
|
|
int destination = *data >> 2;
|
2024-10-06 16:55:36 +02:00
|
|
|
// set auto router map
|
2024-10-07 17:53:56 +02:00
|
|
|
set_auto_router_map(link, Dir(destination));
|
2024-10-06 16:55:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************* INIT SOCKET FUNCTIONS ********************/
|
2024-10-07 17:53:56 +02:00
|
|
|
tlm_sync_enum TlmRouterCS::nb_transport_bw_cb(int id, tlm_gp& trans,
|
2024-10-06 16:55:36 +02:00
|
|
|
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;
|
2024-10-07 22:15:03 +02:00
|
|
|
tlm_sync_enum status = (*target_socket_cs[link])->nb_transport_bw(
|
2024-10-06 16:55:36 +02:00
|
|
|
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);
|
2024-10-07 17:53:56 +02:00
|
|
|
phase = (type == TYPE_STREAM) ? INTERNAL_PROC_PHASE :
|
2024-10-06 16:55:36 +02:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|