generate_benchmark.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. #
  4. # AWL simulator - Generate instruction benchmark
  5. #
  6. # Copyright 2019 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. #
  22. from __future__ import division, absolute_import, print_function, unicode_literals
  23. import sys
  24. import random
  25. import getopt
  26. insnCollection = (
  27. (
  28. ( "U", "BOOL"),
  29. ), (
  30. ( "UN", "BOOL"),
  31. ), (
  32. ( "O", "BOOL"),
  33. ), (
  34. ( "ON", "BOOL"),
  35. ), (
  36. ( "X", "BOOL"),
  37. ), (
  38. ( "XN", "BOOL"),
  39. ), (
  40. ( "U", "RANDOM_BOOL"),
  41. ), (
  42. ( "UN", "RANDOM_BOOL"),
  43. ), (
  44. ( "O", "RANDOM_BOOL"),
  45. ), (
  46. ( "ON", "RANDOM_BOOL"),
  47. ), (
  48. ( "X", "RANDOM_BOOL"),
  49. ), (
  50. ( "XN", "RANDOM_BOOL"),
  51. ), (
  52. ( "U(", ""),
  53. ( ")", ""),
  54. ), (
  55. ( "UN(", ""),
  56. ( ")", ""),
  57. ), (
  58. ( "O(", ""),
  59. ( ")", ""),
  60. ), (
  61. ( "ON(", ""),
  62. ( ")", ""),
  63. ), (
  64. ( "X(", ""),
  65. ( ")", ""),
  66. ), (
  67. ( "XN(", ""),
  68. ( ")", ""),
  69. ), (
  70. ( "=", "BOOL"),
  71. ), (
  72. ( "R", "BOOL"),
  73. ), (
  74. ( "S", "BOOL"),
  75. ), (
  76. ( "NOT", ""),
  77. ), (
  78. ( "SET", ""),
  79. ), (
  80. ( "CLR", ""),
  81. ), (
  82. ( "SAVE", ""),
  83. ), (
  84. ( "FN", "BOOL"),
  85. ), (
  86. ( "FP", "BOOL"),
  87. ), (
  88. ( "==I", ""),
  89. ), (
  90. ( "<>I", ""),
  91. ), (
  92. ( ">I", ""),
  93. ), (
  94. ( "<I", ""),
  95. ), (
  96. ( ">=I", ""),
  97. ), (
  98. ( "<=I", ""),
  99. ), (
  100. ( "==D", ""),
  101. ), (
  102. ( "<>D", ""),
  103. ), (
  104. ( ">D", ""),
  105. ), (
  106. ( "<D", ""),
  107. ), (
  108. ( ">=D", ""),
  109. ), (
  110. ( "<=D", ""),
  111. ), (
  112. ( "==R", ""),
  113. ), (
  114. ( "<>R", ""),
  115. ), (
  116. ( ">R", ""),
  117. ), (
  118. ( "<R", ""),
  119. ), (
  120. ( ">=R", ""),
  121. ), (
  122. ( "<=R", ""),
  123. ), (
  124. ( "L", "0"),
  125. ( "BTI", ""),
  126. ), (
  127. ( "ITB", ""),
  128. ), (
  129. ( "L", "0"),
  130. ( "BTD", ""),
  131. ), (
  132. ( "ITD", ""),
  133. ), (
  134. ( "DTB", ""),
  135. ), (
  136. ( "DTR", ""),
  137. ), (
  138. ( "INVI", ""),
  139. ), (
  140. ( "INVD", ""),
  141. ), (
  142. ( "NEGI", ""),
  143. ), (
  144. ( "NEGD", ""),
  145. ), (
  146. ( "NEGR", ""),
  147. ), (
  148. ( "TAW", ""),
  149. ), (
  150. ( "TAD", ""),
  151. ), (
  152. ( "RND", ""),
  153. ), (
  154. ( "TRUNC", ""),
  155. ), (
  156. ( "RND+", ""),
  157. ), (
  158. ( "RND-", ""),
  159. ), (
  160. ( "FR", "COUNTER"),
  161. ), (
  162. ( "L", "RANDOM_DWORD"),
  163. ), (
  164. ( "LC", "WORD"),
  165. ), (
  166. ( "ZV", "COUNTER"),
  167. ), (
  168. ( "ZR", "COUNTER"),
  169. ), (
  170. ( "AUF", "DB"),
  171. ), (
  172. ( "TDB", ""),
  173. ), (
  174. ( "SPA", "LABEL"),
  175. ), (
  176. ( "L", "0"),
  177. ( "SPL", "LABEL"),
  178. ), (
  179. ( "SPB", "LABEL"),
  180. ), (
  181. ( "SPBN", "LABEL"),
  182. ), (
  183. ( "SPBB", "LABEL"),
  184. ), (
  185. ( "SPBNB", "LABEL"),
  186. ), (
  187. ( "SPBI", "LABEL"),
  188. ), (
  189. ( "SPBIN", "LABEL"),
  190. ), (
  191. ( "SPO", "LABEL"),
  192. ), (
  193. ( "SPS", "LABEL"),
  194. ), (
  195. ( "SPZ", "LABEL"),
  196. ), (
  197. ( "SPN", "LABEL"),
  198. ), (
  199. ( "SPP", "LABEL"),
  200. ), (
  201. ( "SPM", "LABEL"),
  202. ), (
  203. ( "SPPZ", "LABEL"),
  204. ), (
  205. ( "SPMZ", "LABEL"),
  206. ), (
  207. ( "SPU", "LABEL"),
  208. ), (
  209. ( "LOOP", "LABEL"),
  210. ), (
  211. ( "+I", ""),
  212. ), (
  213. ( "-I", ""),
  214. ), (
  215. ( "*I", ""),
  216. ), (
  217. ( "/I", ""),
  218. ), (
  219. ( "+", "0"),
  220. ), (
  221. ( "+D", ""),
  222. ), (
  223. ( "-D", ""),
  224. ), (
  225. ( "*D", ""),
  226. ), (
  227. ( "/D", ""),
  228. ), (
  229. ( "MOD", ""),
  230. ), (
  231. ( "+R", ""),
  232. ), (
  233. ( "-R", ""),
  234. ), (
  235. ( "*R", ""),
  236. ), (
  237. ( "/R", ""),
  238. ), (
  239. ( "ABS", ""),
  240. ), (
  241. ( "SQR", ""),
  242. ), (
  243. ( "SQRT", ""),
  244. ), (
  245. ( "EXP", ""),
  246. ), (
  247. ( "LN", ""),
  248. ), (
  249. ( "SIN", ""),
  250. ), (
  251. ( "COS", ""),
  252. ), (
  253. ( "TAN", ""),
  254. ), (
  255. ( "ASIN", ""),
  256. ), (
  257. ( "ACOS", ""),
  258. ), (
  259. ( "ATAN", ""),
  260. ), (
  261. ( "LAR1", ""),
  262. ), (
  263. ( "LAR2", ""),
  264. ), (
  265. ( "T", "DWORD"),
  266. ), (
  267. ( "TAR", ""),
  268. ), (
  269. ( "TAR1", ""),
  270. ), (
  271. ( "TAR2", ""),
  272. ), (
  273. ( "MCR(", ""),
  274. ( "MCRA", ""),
  275. ( "MCRD", ""),
  276. ( ")MCR", ""),
  277. ), (
  278. ( "SSI", ""),
  279. ), (
  280. ( "SSD", ""),
  281. ), (
  282. ( "SLW", ""),
  283. ), (
  284. ( "SRW", ""),
  285. ), (
  286. ( "SLD", ""),
  287. ), (
  288. ( "SRD", ""),
  289. ), (
  290. ( "RLD", ""),
  291. ), (
  292. ( "RRD", ""),
  293. ), (
  294. ( "RLDA", ""),
  295. ), (
  296. ( "RRDA", ""),
  297. ), (
  298. ( "L", "0"),
  299. ( "SI", "TIMER"),
  300. ), (
  301. ( "L", "0"),
  302. ( "SV", "TIMER"),
  303. ), (
  304. ( "L", "0"),
  305. ( "SE", "TIMER"),
  306. ), (
  307. ( "L", "0"),
  308. ( "SS", "TIMER"),
  309. ), (
  310. ( "L", "0"),
  311. ( "SA", "TIMER"),
  312. ), (
  313. ( "UW", ""),
  314. ), (
  315. ( "OW", ""),
  316. ), (
  317. ( "XOW", ""),
  318. ), (
  319. ( "UD", ""),
  320. ), (
  321. ( "OD", ""),
  322. ), (
  323. ( "XOD", ""),
  324. ), (
  325. ( "TAK", ""),
  326. ), (
  327. ( "PUSH", ""),
  328. ), (
  329. ( "POP", ""),
  330. ), (
  331. ( "ENT", ""),
  332. ), (
  333. ( "LEAVE", ""),
  334. ), (
  335. ( "INC", "0"),
  336. ), (
  337. ( "DEC", "0"),
  338. ), (
  339. ( "+AR1", ""),
  340. ), (
  341. ( "+AR2", ""),
  342. ), (
  343. ( "BLD", "0"),
  344. ), (
  345. ( "NOP", "0"),
  346. ), (
  347. ( "CALL", "FC 42"),
  348. ( "CALL", "FC 42"),
  349. ( "CALL", "FC 42"),
  350. ), (
  351. ( "CALL", "FB 45, DB 45"),
  352. ( "CALL", "FB 45, DB 45"),
  353. ( "CALL", "FB 45, DB 45"),
  354. ), (
  355. ( "SET", ""),
  356. ), (
  357. ( "CC", "FC 43"),
  358. ), (
  359. ( "UC", "FC 44"),
  360. ), (
  361. # Write some values to the HW module.
  362. ( "L", "MW 50"),
  363. ( "+", "1"),
  364. ( "T", "MW 50"),
  365. ( "T", "AW 0" )
  366. )
  367. )
  368. def out(data):
  369. print(data, end="\r\n")
  370. def error(msg):
  371. print(msg, file=sys.stderr)
  372. sys.exit(1)
  373. def usage(f=sys.stdout):
  374. print("generate_benchmark.py [OPTIONS]", file=f)
  375. print("", file=f)
  376. print(" -s|--seed SEED Set the randomizer seed. Default: 42", file=f)
  377. print(" -i|--iterations COUNT Set the number of iterations. Default: 10000", file=f)
  378. print(" -o|--one-cycle Generate CALL SFC 46 at the end of OB 1.", file=f)
  379. def getLabelName(index):
  380. if index < 0 or index >= 26 ** 4:
  381. raise ValueError("Label index out of range.")
  382. labelChars = [None] * 4
  383. for i in range(3, -1, -1):
  384. labelChars[i] = chr(ord("A") + (index % 26))
  385. index //= 26
  386. return "".join(labelChars)
  387. def main():
  388. opt_nrIterations = 10000
  389. opt_rngSeed = 42
  390. opt_oneCycle = False
  391. try:
  392. (opts, args) = getopt.getopt(sys.argv[1:],
  393. "hs:i:o",
  394. [ "help", "seed=", "iterations=", "one-cycle", ])
  395. except getopt.GetoptError as e:
  396. error(str(e))
  397. for (o, v) in opts:
  398. if o in ("-h", "--help"):
  399. usage()
  400. return 0
  401. if o in ("-s", "--seed"):
  402. try:
  403. opt_rngSeed = int(v)
  404. if opt_rngSeed < 0 or opt_rngSeed > 0xFFFFFFFF:
  405. raise ValueError
  406. except ValueError:
  407. error("Invalid RNG seed.")
  408. if o in ("-i", "--iterations"):
  409. try:
  410. opt_nrIterations = int(v)
  411. if opt_nrIterations < 0:
  412. raise ValueError
  413. except ValueError:
  414. error("Invalid number of iterations.")
  415. if o in ("-o", "--one-cycle"):
  416. opt_oneCycle = True
  417. if args:
  418. usage(f=sys.stderr)
  419. return 1
  420. rng = random.Random()
  421. rng.seed(opt_rngSeed)
  422. labelIndex = 0
  423. out("//")
  424. out("//")
  425. out("// GENERATED by generate_benchmark.py")
  426. out("//")
  427. out("// iterations=%d" % opt_nrIterations)
  428. out("// seed=%d" % opt_rngSeed)
  429. out("//")
  430. out("//")
  431. out("")
  432. out("ORGANIZATION_BLOCK OB 1")
  433. out("BEGIN")
  434. for i in range(opt_nrIterations):
  435. for insn, args in rng.choice(insnCollection):
  436. prefixStr = suffixStr = None
  437. if args == "":
  438. argsStr = ""
  439. elif args == "BOOL":
  440. argsStr = "M 0.4"
  441. elif args == "WORD":
  442. argsStr = "MW 0"
  443. elif args == "DWORD":
  444. argsStr = "MD 0"
  445. elif args == "TIMER":
  446. argsStr = "T 42"
  447. elif args == "COUNTER":
  448. argsStr = "Z 42"
  449. elif args == "DB":
  450. argsStr = "DB 42"
  451. elif args == "LABEL":
  452. try:
  453. labelName = getLabelName(labelIndex)
  454. except ValueError as e:
  455. error("Failed to generate jump label: %s\n"
  456. "The generated program is too big." % str(e))
  457. prefixStr = "\tL 0;\r\n\tCLR;"
  458. argsStr = labelName
  459. suffixStr = "%s:\tNOP 0;" % labelName
  460. labelIndex += 1
  461. elif args == "RANDOM_BOOL":
  462. argsStr = "TRUE" if rng.randint(0, 1) else "FALSE"
  463. elif args == "RANDOM_DWORD":
  464. argsStr = "DW#16#%08X" % rng.randint(0, 0xFFFFFFFF)
  465. else:
  466. argsStr = args
  467. if prefixStr:
  468. out(prefixStr)
  469. if argsStr:
  470. argsStr = " " + argsStr
  471. out("\t%s%s;" % (insn, argsStr))
  472. if suffixStr:
  473. out(suffixStr)
  474. if opt_oneCycle:
  475. out("\tCALL SFC 46 // STOP CPU")
  476. out("END_ORGANIZATION_BLOCK")
  477. out("\r\nDATA_BLOCK DB 42")
  478. out("\tSTRUCT")
  479. out("\t\tVAR : INT;")
  480. out("\tEND_STRUCT")
  481. out("BEGIN")
  482. out("END_DATA_BLOCK")
  483. out("\r\nFUNCTION FC 42 : VOID")
  484. out("BEGIN")
  485. out("\tBE;")
  486. out("END_FUNCTION")
  487. out("\r\nFUNCTION FC 43 : VOID")
  488. out("BEGIN")
  489. out("\tBEA")
  490. out("END_FUNCTION")
  491. out("\r\nFUNCTION FC 44 : VOID")
  492. out("BEGIN")
  493. out("\tSET;")
  494. out("\tBEB;")
  495. out("END_FUNCTION")
  496. out("\r\nFUNCTION_BLOCK FB 45")
  497. out("BEGIN")
  498. out("END_FUNCTION_BLOCK")
  499. out("\r\nDATA_BLOCK DB 45")
  500. out("\tFB 45")
  501. out("BEGIN")
  502. out("END_DATA_BLOCK")
  503. if __name__ == "__main__":
  504. sys.exit(main())