PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/patterns/components/routermodel/routermodel.cc

https://gitlab.com/pranith/sst-elements
C++ | 352 lines | 182 code | 67 blank | 103 comment | 29 complexity | 1f99dc40e653f11cc6f84e0a96de332b MD5 | raw file
  1. // Copyright 2009-2015 Sandia Corporation. Under the terms
  2. // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
  3. // Government retains certain rights in this software.
  4. //
  5. // Copyright (c) 2009-2015, Sandia Corporation
  6. // All rights reserved.
  7. //
  8. // This file is part of the SST software package. For license
  9. // information, see the LICENSE file in the top level directory of the
  10. // distribution.
  11. #include <sst_config.h>
  12. #include <sst/core/serialization.h>
  13. #include "routermodel.h"
  14. #include <assert.h>
  15. #include "sst/core/element.h"
  16. #include <cpunicEvent.h>
  17. // The lower 27 bits of the event ID are the rank number, high order bits are sequence
  18. #define RANK_FIELD (27)
  19. void
  20. Routermodel::handle_port_events(Event *event, int in_port)
  21. {
  22. SimTime_t current_time;
  23. SimTime_t delay = 0;
  24. SimTime_t link_time;
  25. SimTime_t blocked;
  26. int out_port;
  27. // Check for routing algorithm problems
  28. assert((in_port >= 0) && (in_port < num_ports));
  29. current_time= getCurrentSimTime();
  30. CPUNicEvent *e= static_cast<CPUNicEvent *>(event);
  31. _ROUTER_MODEL_DBG(4, "%s in port %d, time %" PRIu64 ", src %" PRId64 ", seq %" PRId64 "\n",
  32. component_name.c_str(), in_port, (uint64_t)current_time,
  33. e->msg_id & ((1 << RANK_FIELD) - 1), e->msg_id >> RANK_FIELD);
  34. #if DBG_ROUTER_MODEL > 1
  35. /* Diagnostic: print the route this event is taking */
  36. if (router_model_debug >= 5) {
  37. std::vector<int>::iterator itNum;
  38. char str[132];
  39. char tmp[132];
  40. int i= 0;
  41. sprintf(str, "%s event route: ", component_name.c_str());
  42. for(itNum = e->route.begin(); itNum < e->route.end(); itNum++) {
  43. if (i == e->hops) {
  44. sprintf(tmp, "%s%c", str, '[');
  45. strcpy(str, tmp);
  46. }
  47. // str= str + boost::lexical_cast<std::string>(*itNum);
  48. sprintf(tmp, "%s%d", str, *itNum);
  49. strcpy(str, tmp);
  50. if (i == e->hops) {
  51. sprintf(tmp, "%s%c", str, ']');
  52. strcpy(str, tmp);
  53. }
  54. sprintf(tmp, "%s%c", str, ' ');
  55. strcpy(str, tmp);
  56. i++;
  57. }
  58. _ROUTER_MODEL_DBG(5, "%s\n", str);
  59. }
  60. #endif // DBG_ROUTER_MODEL
  61. // Where are we going?
  62. out_port= e->route[e->hops];
  63. assert((out_port >= 0) && (out_port < num_ports));
  64. if (aggregator) {
  65. // We're not really a router, rather we are being used as an aggregator
  66. // Just send the event on: no delays, no queuing
  67. e->hops++;
  68. assert(port[out_port].link); // Trying to use an unused port. This is a routing error
  69. port[out_port].link->send(0, e);
  70. return;
  71. }
  72. if (port[in_port].next_in > current_time) {
  73. SimTime_t arrival_delay;
  74. // If the input port is in use right now, then this message actually
  75. // wont come in until later
  76. arrival_delay= port[in_port].next_in - current_time;
  77. port[in_port].next_in= current_time + arrival_delay;
  78. // FIXME: I am not sure these are meaningful statistics
  79. congestion_in_cnt++;
  80. congestion_in += arrival_delay;
  81. e->congestion_cnt++;
  82. e->congestion_delay += arrival_delay;
  83. e->entry_port= in_port;
  84. assert(self_link); // Trying to use an unused port. This is a routing error
  85. self_link->send(arrival_delay, e);
  86. return;
  87. }
  88. // We'll take it now
  89. port[in_port].cnt_in++;
  90. // Update total usage counts of all ports for power
  91. if (!e->local_traffic) {
  92. #ifdef WITH_POWER
  93. mycounts.router_access++;
  94. #endif
  95. } else {
  96. num_local_message++;
  97. }
  98. // What is the current delay to send on this output port?
  99. if (!new_model) {
  100. if (port[out_port].next_out <= current_time) {
  101. // No output port delays. We can send as soon as the message arrives;
  102. delay= 0;
  103. blocked= 0;
  104. } else {
  105. // Busy right now
  106. blocked= port[out_port].next_out - current_time;
  107. congestion_out_cnt++;
  108. congestion_out += blocked;
  109. e->congestion_cnt++;
  110. e->congestion_delay += blocked;
  111. }
  112. // Add in the generic router delay
  113. delay += hop_delay;
  114. // For introspection (router_delay)
  115. router_totaldelay= router_totaldelay + e->congestion_delay + delay;
  116. // How long will this message occupy the input and output port?
  117. // FIXME: The constant 1000000000 should be replaced with our time base
  118. link_time= ((uint64_t)e->msg_len * 1000000000) / router_bw;
  119. } else {
  120. // Calculate when this message can leave the router port
  121. delay= get_Rtrparams(Rtrparams, e->msg_len);
  122. link_time= get_Rtrparams(NICparams, e->msg_len);
  123. if (current_time >= port[out_port].next_out) {
  124. // Port is not busy
  125. blocked= 0.0;
  126. } else {
  127. // Port is busy
  128. blocked= port[out_port].next_out - current_time ;
  129. congestion_out_cnt++;
  130. congestion_out += blocked;
  131. e->congestion_cnt++;
  132. e->congestion_delay += blocked;
  133. }
  134. }
  135. // When can these ports be used again?
  136. port[out_port].next_out= current_time + blocked + delay + link_time;
  137. port[in_port].next_in= current_time + blocked + link_time;
  138. e->hops++;
  139. assert(port[out_port].link); // Trying to use an unused port. This is a routing error
  140. port[out_port].link->send(delay + blocked, e);
  141. port[out_port].cnt_out++;
  142. msg_cnt++;
  143. } // end of handle_port_events()
  144. // When we send to ourselves, we come here.
  145. // Just pass it on to the main handler above
  146. void
  147. Routermodel::handle_self_events(Event *event)
  148. {
  149. CPUNicEvent *e= static_cast<CPUNicEvent *>(event);
  150. if (e->entry_port < 0) {
  151. out.fatal(CALL_INFO, -1, "Internal error: entry port not defined!\n");
  152. }
  153. handle_port_events(e, e->entry_port);
  154. } /* end of handle_self_events() */
  155. #ifdef WITH_POWER
  156. // Get and push power at a frequency determinedby the push_introspector
  157. bool
  158. Routermodel::pushData(Cycle_t current)
  159. {
  160. if (isTimeToPush(current, pushIntrospector.c_str())) {
  161. // Here you can push power statistics by 1) set up values in the mycounts structure
  162. // and 2) call the gerPower function. See cpu_PowerAndData for example
  163. // set up counts
  164. // set up router-related counts (in this case, this is done in handle_port_event)
  165. // mycounts.router_access=1;
  166. // std::cout << " It is time (" <<current << ") to push power, router_delay = " << router_totaldelay << " and router_access = " << mycounts.router_access << std::endl;
  167. pdata= power->getPower(this, ROUTER, mycounts);
  168. power->compute_temperature(getId());
  169. regPowerStats(pdata);
  170. //reset all counts to zero for next power query
  171. power->resetCounts(&mycounts);
  172. #if 0
  173. using namespace io_interval; std::cout <<"ID " << getId() <<": current total power = " << pdata.currentPower << " W" << std::endl;
  174. using namespace io_interval; std::cout <<"ID " << getId() <<": leakage power = " << pdata.leakagePower << " W" << std::endl;
  175. using namespace io_interval; std::cout <<"ID " << getId() <<": runtime power = " << pdata.runtimeDynamicPower << " W" << std::endl;
  176. using namespace io_interval; std::cout <<"ID " << getId() <<": total energy = " << pdata.totalEnergy << " J" << std::endl;
  177. using namespace io_interval; std::cout <<"ID " << getId() <<": peak power = " << pdata.peak << " W" << std::endl;
  178. #endif
  179. }
  180. return false;
  181. } // end of pushData()
  182. #endif
  183. // Based on message length and the router parameter list, extract the
  184. // delay this message will experience on the output port.
  185. int64_t
  186. Routermodel::get_Rtrparams(std::list<Rtrparams_t> params, int64_t msg_len)
  187. {
  188. std::list<Rtrparams_t>::iterator k;
  189. std::list<Rtrparams_t>::iterator previous;
  190. double T, B;
  191. double byte_cost;
  192. int64_t latency;
  193. previous= params.begin();
  194. k= previous;
  195. k++;
  196. for (; k != params.end(); k++) {
  197. if (k->inflectionpoint > msg_len) {
  198. T= k->latency - previous->latency;
  199. B= k->inflectionpoint - previous->inflectionpoint;
  200. byte_cost= T / B;
  201. if (byte_cost < 0) {
  202. // FIXME: Not sure this is a good decision
  203. byte_cost= 0;
  204. }
  205. // We want the values from the previous point
  206. if (previous->latency < 0) {
  207. latency= 0;
  208. } else {
  209. latency= previous->latency;
  210. }
  211. return (int64_t)((double)(msg_len - previous->inflectionpoint) * byte_cost) + latency;
  212. }
  213. previous++;
  214. }
  215. // We're beyond the list. Use the last two values in the list and
  216. // extrapolite.
  217. previous--;
  218. T= params.back().latency - previous->latency;
  219. B= params.back().inflectionpoint - previous->inflectionpoint;
  220. byte_cost= T / B;
  221. if (byte_cost < 0) {
  222. // FIXME: Not sure this is a good decision
  223. byte_cost= 0;
  224. }
  225. if (previous->latency < 0) {
  226. latency= 0;
  227. } else {
  228. latency= previous->latency;
  229. }
  230. return (int64_t)((double)(msg_len - previous->inflectionpoint) * byte_cost) + latency;
  231. } // end of getRtrparams()
  232. /*
  233. // THIS SECTION MOVED TO patterns.cc FOR RELEASE 3.x OF SST - ALEVINE
  234. static Component*
  235. create_routermodel(SST::ComponentId_t id,
  236. SST::Params& params)
  237. {
  238. return new Routermodel( id, params );
  239. }
  240. static const ElementInfoComponent components1[] = {
  241. { "routermodel",
  242. "router model without power",
  243. NULL,
  244. create_routermodel
  245. },
  246. { NULL, NULL, NULL, NULL }
  247. };
  248. extern "C" {
  249. ElementLibraryInfo routermodel_eli = {
  250. "routermodel",
  251. "router model without power",
  252. components1,
  253. };
  254. }
  255. static Component*
  256. create_routermodel_power(SST::ComponentId_t id,
  257. SST::Params& params)
  258. {
  259. return new Routermodel( id, params );
  260. }
  261. static const ElementInfoComponent components2[] = {
  262. { "routermodel_power",
  263. "router model with power",
  264. NULL,
  265. create_routermodel_power
  266. },
  267. { NULL, NULL, NULL, NULL }
  268. };
  269. extern "C" {
  270. ElementLibraryInfo routermodel_power_eli = {
  271. "routermodel_power",
  272. "router model with power",
  273. components2,
  274. };
  275. }
  276. */
  277. BOOST_CLASS_EXPORT(Routermodel)