tlm_noc_sim/src/noc/noc.cpp

188 lines
6.9 KiB
C++
Executable file

/*******************************************************************************
* 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 "noc.h"
#include "utils/noc_logger.h"
#include "utils/utils.h"
using namespace std;
TlmNoc::TlmNoc(sc_module_name nm, string config_folder): sc_module(nm){
setup_logger();
sc_report_handler::set_actions(N_LOG, SC_INFO, SC_LOG|SC_DISPLAY);
initializeGlobalResources(config_folder);
initNoc();
connectNoc();
}
TlmNoc::~TlmNoc() {
}
void TlmNoc::initializeGlobalResources(string config_folder) {
// initialize global resources and rep
globalResources = GlobalResources::getInstance();
GlobalReport &globalReport = GlobalReport::getInstance();
Report &rep = Report::getInstance();
sleep(1);
string config_path = "config/"+config_folder+"/config.xml";//"config/config.xml";
globalResources.readConfigFile(config_path);
globalReport.readConfigFile(config_path);
string network_path = "config/"+config_folder+"/net.xml";
//globalResources.noc_file;
globalResources.readNoCLayout(network_path);
globalResources.readTaskAndMapFiles(globalResources.data_file, globalResources.map_file);
globalReport.resizeMatrices();
globalResources.activateFlitTracing = false;
globalResources.outputDirectory = "out";
}
void TlmNoc::initNoc() {
uint8_t max_pos[3];
get_max_pos(max_pos);
for (Node &n : globalResources.nodes) {
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);
string msg = " initialized in position " +
to_string(rout_pos[0]) + "," + to_string(rout_pos[1])+
"," + to_string(rout_pos[2]);
string rout_name = "router_" + to_string(n.id);
TlmRouter* r = new TlmRouter(rout_name.c_str(), rout_pos, max_pos);
routers.push_back(r);
mapNodeRouter.insert(
pair<int,int>(n.id, int(routers.size())-1));
log_info(rout_name + msg);
}
}
}
void TlmNoc::connectRouters(Node node1, Node node2, int link){
bool is_n1_router = node1.type->model=="Router";
bool is_n1_router_cs = node1.type->model=="RouterCS";
bool is_n2_router = node2.type->model=="Router";
bool is_n2_router_cs = node2.type->model=="RouterCS";
int n1_id = mapNodeRouter[node1.id];
int n2_id = mapNodeRouter[node2.id];
if((is_n1_router||is_n1_router_cs) && (is_n2_router||is_n2_router_cs)){
int connDir = node1.getDirOfCon(link);
int opposDir = DIR::getOppositeDir(connDir);
routers[n1_id]->init_socket[connDir]->bind(
*routers[n2_id]->target_socket[opposDir]);
routers[n2_id]->init_socket[opposDir]->bind(
*routers[n1_id]->target_socket[connDir]);
routers[n1_id]->valid_links[connDir] = true;
routers[n2_id]->valid_links[opposDir] = true;
log_conn(routers[n1_id]->router_name,
routers[n2_id]->router_name,
DIR::toString(connDir), DIR::toString(opposDir));
}
else{
int r_id = (is_n1_router || is_n1_router_cs) ? 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;
log_conn(routers[r_id]->router_name, "noc interface",
DIR::toString(DIR::Local), "external");
}
}
void TlmNoc::connectUnbounded(){
// connecting unbounded routers
for (uint8_t id=0; id < routers.size(); id++){
for (uint8_t dir=0; dir < Direction::num_dirs; dir++){
if (!routers[id]->valid_links[dir]){
tlm_init_socket* unbound_init = new tlm_init_socket(
("unb_init_"+to_string(id)+"_"+to_string(dir)).c_str());
unbound_init->bind(*routers[id]->target_socket[dir]);
unbounded_initiators.push_back(unbound_init);
tlm_targ_socket* unbound_targ = new tlm_targ_socket(
("unb_targ_"+to_string(id)+"_"+to_string(dir)).c_str());
routers[id]->init_socket[dir]->bind(*unbound_targ);
unbounded_targets.push_back(unbound_targ);
log_conn(routers[id]->router_name, "unbounded_" +
to_string(id)+"_"+to_string(dir),
DIR::toString(dir), "unbounded");
}
}
}
}
void TlmNoc::connectNoc(){
int link_id = 0;
for (auto &c : globalResources.connections) {
if(c.nodes.size() == 2){
Node &node1 = globalResources.nodes.at(c.nodes.at(0));
Node &node2 = globalResources.nodes.at(c.nodes.at(1));
connectRouters(node1, node2, c.id);
link_id += 2;
} else {
log_error("Unsupported number of endpoints in connection "
+ to_string(c.id));
}
}
connectUnbounded();
}
TlmRouter* TlmNoc::getRouter(int id){
return routers.at(id);
}
TlmRouter* TlmNoc::getRouterNodeId(int node_id){
int rout_id = mapNodeRouter.find(node_id)->first;
return routers.at(rout_id);
}
/******************* LOG FUNCTIONS ********************/
void TlmNoc::log_info(string msg){
SC_REPORT_INFO(N_LOG, (msg).c_str());
}
void TlmNoc::log_warn(string msg){
SC_REPORT_WARNING(N_LOG, (msg).c_str());
}
void TlmNoc::log_error(string msg){
SC_REPORT_ERROR(N_LOG, (msg).c_str());
}
void TlmNoc::log_conn(string router1, string router2,
string link1, string link2){
string msg = router1 + " on link " + link1 + " connected to " +
router2 + " on link " + link2;
log_info(msg);
}