suck.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #define ESTR 256
  12. static void
  13. error(char* fmt, ...)
  14. {
  15. va_list v;
  16. char *e, estr[ESTR], *p;
  17. va_start(v, fmt);
  18. e = estr + ESTR;
  19. p = seprint(estr, e, "%s: ", argv0);
  20. p = vseprint(p, e, fmt, v);
  21. p = seprint(p, e, "\n");
  22. va_end(v);
  23. write(2, estr, p-estr);
  24. }
  25. static void
  26. fatal(char* fmt, ...)
  27. {
  28. va_list v;
  29. char *e, estr[ESTR], *p;
  30. va_start(v, fmt);
  31. e = estr + ESTR;
  32. p = seprint(estr, e, "%s: ", argv0);
  33. p = vseprint(p, e, fmt, v);
  34. p = seprint(p, e, "\n");
  35. va_end(v);
  36. write(2, estr, p - estr);
  37. exits("fatal");
  38. }
  39. static void
  40. usage(void)
  41. {
  42. char *e, estr[ESTR], *p;
  43. e = estr + ESTR;
  44. p = seprint(estr, e, "usage: %s"
  45. " [whatever]"
  46. "\n",
  47. argv0);
  48. write(2, estr, p-estr);
  49. exits("usage");
  50. }
  51. #define F(v, o, w) (((v) & ((1<<(w))-1))<<(o))
  52. enum {
  53. X = 0, /* dimension */
  54. Y = 1,
  55. Z = 2,
  56. N = 3,
  57. Chunk = 32, /* granularity of FIFO */
  58. Pchunk = 8, /* Chunks in a packet */
  59. Quad = 16,
  60. };
  61. /*
  62. * Packet header. The hardware requires an 8-byte header
  63. * of which the last two are reserved (they contain a sequence
  64. * number and a header checksum inserted by the hardware).
  65. * The hardware also requires the packet to be aligned on a
  66. * 128-bit boundary for loading into the HUMMER.
  67. */
  68. typedef struct Tpkt Tpkt;
  69. struct Tpkt {
  70. uint8_t sk; /* Skip Checksum Control */
  71. uint8_t hint; /* Hint|Dp|Pid0 */
  72. uint8_t size; /* Size|Pid1|Dm|Dy|VC */
  73. uint8_t dst[N]; /* Destination Coordinates */
  74. uint8_t _6_[2]; /* reserved */
  75. uint8_t _8_[8]; /* protocol header */
  76. uint8_t payload[];
  77. };
  78. /*
  79. * SKIP is a field in .sk giving the number of 2-bytes
  80. * to skip from the top of the packet before including
  81. * the packet bytes into the running checksum.
  82. * SIZE is a field in .size giving the size of the
  83. * packet in 32-byte 'chunks'.
  84. */
  85. #define SKIP(n) F(n, 1, 7)
  86. #define SIZE(n) F(n, 5, 3)
  87. enum {
  88. Sk = 0x01, /* Skip Checksum */
  89. Pid0 = 0x01, /* Destination Group FIFO MSb */
  90. Dp = 0x02, /* Multicast Deposit */
  91. Hzm = 0x04, /* Z- Hint */
  92. Hzp = 0x08, /* Z+ Hint */
  93. Hym = 0x10, /* Y- Hint */
  94. Hyp = 0x20, /* Y+ Hint */
  95. Hxm = 0x40, /* X- Hint */
  96. Hxp = 0x80, /* X+ Hint */
  97. Vcd0 = 0x00, /* Dynamic 0 VC */
  98. Vcd1 = 0x01, /* Dynamic 1 VC */
  99. Vcbn = 0x02, /* Deterministic Bubble VC */
  100. Vcbp = 0x03, /* Deterministic Priority VC */
  101. Dy = 0x04, /* Dynamic Routing */
  102. Dm = 0x08, /* DMA Mode */
  103. Pid1 = 0x10, /* Destination Group FIFO LSb */
  104. };
  105. static int
  106. torusparse(uint8_t d[3], char* item, char* buf)
  107. {
  108. int n;
  109. char *p;
  110. if((p = strstr(buf, item)) == nil || (p != buf && *(p-1) != '\n'))
  111. return -1;
  112. n = strlen(item);
  113. if(strlen(p) < n+sizeof(": x 0 y 0 z 0"))
  114. return -1;
  115. p += n+sizeof(": x ")-1;
  116. if(strncmp(p-4, ": x ", 4) != 0)
  117. return -1;
  118. if((n = strtol(p, &p, 0)) > 255 || *p != ' ' || *(p+1) != 'y')
  119. return -1;
  120. d[0] = n;
  121. if((n = strtol(p+2, &p, 0)) > 255 || *p != ' ' || *(p+1) != 'z')
  122. return -1;
  123. d[1] = n;
  124. if((n = strtol(p+2, &p, 0)) > 255 || (*p != '\n' && *p != '\0'))
  125. return -1;
  126. d[2] = n;
  127. return 0;
  128. }
  129. static void
  130. dumptpkt(Tpkt* tpkt, int hflag, int dflag)
  131. {
  132. uint8_t *t;
  133. int i, j, n;
  134. char buf[512], *e, *p;
  135. n = ((tpkt->size>>5)+1) * Chunk;
  136. p = buf;
  137. e = buf + sizeof(buf);
  138. if(hflag){
  139. p = seprint(p, e, "Hw:");
  140. #ifdef notdef
  141. p = seprint(p, e, " sk %#2.2ux (Skip %d Sk %d)",
  142. tpkt->sk, tpkt->sk & Sk, tpkt->sk>>1);
  143. p = seprint(p, e, " hint %#2.2ux", tpkt->hint);
  144. p = seprint(p, e, " size %#2.2ux", tpkt->size);
  145. p = seprint(p, e, " dst [%d, %d, %d]",
  146. tpkt->dst[X], tpkt->dst[Y], tpkt->dst[Z]);
  147. p = seprint(p, e, " _6_[0] %#2.2ux (seqno %d)",
  148. tpkt->_6_[0], tpkt->_6_[0]);
  149. p = seprint(p, e, " _6_[1] %#2.2ux (crc)\n", tpkt->_6_[1]);
  150. #else
  151. t = (uint8_t*)tpkt;
  152. for(i = 0; i < 8; i++)
  153. p = seprint(p, e, " %2.2x", t[i]);
  154. p = seprint(p, e, "\n");
  155. #endif /* notdef */
  156. p = seprint(p, e, "Sw:");
  157. t = (uint8_t*)tpkt->_8_;
  158. for(i = 0; i < 8; i++)
  159. p = seprint(p, e, " %#2.2ux", t[i]);
  160. print("%s\n", buf);
  161. }
  162. if(!dflag)
  163. return;
  164. n -= sizeof(Tpkt);
  165. for(i = 0; i < n; i += 16){
  166. p = seprint(buf, e, "%4.4x:", i);
  167. for(j = 0; j < 16; j++)
  168. seprint(p, e, " %2.2x", tpkt->payload[i+j]);
  169. print("%s\n", buf);
  170. }
  171. }
  172. void
  173. main(int argc, char* argv[])
  174. {
  175. Tpkt *tpkt;
  176. u8int d[N];
  177. char buf[512], *p;
  178. uint64_t r, start, stop;
  179. int count, dflag, fd, i, hflag, length, mhz, n;
  180. count = 1;
  181. dflag = hflag = 0;
  182. length = Pchunk*Chunk;
  183. mhz = 700;
  184. ARGBEGIN{
  185. default:
  186. usage();
  187. break;
  188. case 'd':
  189. dflag = 1;
  190. break;
  191. case 'h':
  192. hflag = 1;
  193. break;
  194. case 'l':
  195. p = EARGF(usage());
  196. if((n = strtol(argv[0], &p, 0)) <= 0 || p == argv[0] || *p != 0)
  197. usage();
  198. if(n % Chunk)
  199. usage();
  200. length = n;
  201. if(length > Pchunk*Chunk){
  202. n = (n + (Pchunk*Chunk)-1)/(Pchunk*Chunk);
  203. length += (n-1) * sizeof(Tpkt);
  204. }
  205. break;
  206. case 'm':
  207. p = EARGF(usage());
  208. if((n = strtol(argv[0], &p, 0)) <= 0 || p == argv[0] || *p != 0)
  209. usage();
  210. mhz = n;
  211. break;
  212. case 'n':
  213. p = EARGF(usage());
  214. if((n = strtol(argv[0], &p, 0)) <= 0 || p == argv[0] || *p != 0)
  215. usage();
  216. count = n;
  217. break;
  218. }ARGEND;
  219. if((fd = open("/dev/torusstatus", OREAD)) < 0)
  220. fatal("open /dev/torusstatus: %r\n");
  221. if((n = read(fd, buf, sizeof(buf))) < 0)
  222. fatal("read /dev/torusstatus: %r\n");
  223. close(fd);
  224. buf[n] = 0;
  225. if(torusparse(d, "addr", buf) < 0)
  226. fatal("parse /dev/torusstatus: <%s>\n", buf);
  227. print("addr: %d.%d.%d\n", d[X], d[Y], d[Z]);
  228. if(torusparse(d, "size", buf) < 0)
  229. fatal("parse /dev/torusstatus: <%s>\n", buf);
  230. print("size: %d.%d.%d\n", d[X], d[Y], d[Z]);
  231. if((tpkt = mallocalign(length, Chunk, 0, 0)) == nil)
  232. fatal("mallocalign tpkt\n");
  233. if((fd = open("/dev/torus", ORDWR)) < 0)
  234. fatal("open /dev/torus: %r\n");
  235. print("starting %d reads of %d\n", count, length);
  236. r = count*length;
  237. cycles(&start);
  238. for(i = 0; i < r; i += n){
  239. if((n = pread(fd, tpkt, length, 0)) < 0)
  240. fatal("read /dev/torus: %r\n", n);
  241. if(hflag || dflag)
  242. dumptpkt(tpkt, hflag, dflag);
  243. }
  244. cycles(&stop);
  245. close(fd);
  246. r = (count*length);
  247. r *= mhz;
  248. r /= stop - start;
  249. print("%d reads in %llu cycles @ %dMHz = %llu MB/s\n",
  250. i, stop - start, mhz, r);
  251. exits(0);
  252. }