Advertisement
Guest User

Untitled

a guest
Apr 19th, 2018
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.25 KB | None | 0 0
  1. //
  2. // device.c: CEN64 device container.
  3. //
  4. // CEN64: Cycle-Accurate Nintendo 64 Emulator.
  5. // Copyright (C) 2015, Tyler J. Stachecki.
  6. //
  7. // This file is subject to the terms and conditions defined in
  8. // 'LICENSE', which is part of this source code package.
  9. //
  10.  
  11. #include "common.h"
  12. #include "device/device.h"
  13. #include "device/netapi.h"
  14. #include "fpu/fpu.h"
  15. #include "gl_window.h"
  16. #include "os/common/rom_file.h"
  17. #include "os/common/save_file.h"
  18. #include "os/cpuid.h"
  19.  
  20. #include "bus/controller.h"
  21. #include "ai/controller.h"
  22. #include "dd/controller.h"
  23. #include "pi/controller.h"
  24. #include "ri/controller.h"
  25. #include "si/controller.h"
  26. #include "rsp/cpu.h"
  27. #include "thread.h"
  28. #include "vi/controller.h"
  29. #include "vr4300/cpu.h"
  30. #include "vr4300/cp1.h"
  31. #include <setjmp.h>
  32.  
  33. cen64_cold int angrylion_rdp_init(struct cen64_device *device);
  34. cen64_cold static int device_debug_spin(struct cen64_device *device);
  35. cen64_cold static void device_schedule_threads(unsigned num_threads, cen64_thread **threads);
  36. cen64_flatten cen64_hot static int device_multithread_spin(struct cen64_device *device);
  37. cen64_flatten cen64_hot static int device_spin(struct cen64_device *device);
  38. cen64_flatten cen64_hot static int device_unthreaded_spin(struct cen64_device *device);
  39.  
  40. cen64_flatten cen64_hot static CEN64_THREAD_RETURN_TYPE run_rcp_thread(void *);
  41. cen64_flatten cen64_hot static CEN64_THREAD_RETURN_TYPE run_vr4300_thread(void *);
  42.  
  43. // Creates and initializes a device.
  44. struct cen64_device *device_create(struct cen64_device *device,
  45. const struct rom_file *ddipl, const struct dd_variant *dd_variant,
  46. const struct rom_file *ddrom,
  47. const struct rom_file *pifrom, const struct rom_file *cart,
  48. const struct save_file *eeprom, const struct save_file *sram,
  49. const struct save_file *flashram, const struct controller *controller,
  50. bool no_audio, bool no_video) {
  51.  
  52. // Initialize the bus.
  53. device->bus.ai = &device->ai;
  54. device->bus.dd = &device->dd;
  55. device->bus.pi = &device->pi;
  56. device->bus.ri = &device->ri;
  57. device->bus.si = &device->si;
  58. device->bus.vi = &device->vi;
  59.  
  60. device->bus.rdp = &device->rdp;
  61. device->bus.rsp = &device->rsp;
  62. device->bus.vr4300 = &device->vr4300;
  63.  
  64. // Initialize the bus.
  65. if (bus_init(&device->bus, dd_variant != NULL)) {
  66. debug("create_device: Failed to initialize the bus.\n");
  67. return NULL;
  68. }
  69.  
  70. // Initialize the AI.
  71. if (ai_init(&device->ai, &device->bus, no_audio)) {
  72. debug("create_device: Failed to initialize the AI.\n");
  73. return NULL;
  74. }
  75.  
  76. // Initialize the DD.
  77. if (dd_init(&device->dd, &device->bus,
  78. ddipl->ptr, ddrom->ptr, ddrom->size)) {
  79. debug("create_device: Failed to initialize the DD.\n");
  80. return NULL;
  81. }
  82.  
  83. // Initialize the PI.
  84. if (pi_init(&device->pi, &device->bus, cart->ptr, cart->size, sram, flashram)) {
  85. debug("create_device: Failed to initialize the PI.\n");
  86. return NULL;
  87. }
  88.  
  89. // Initialize the RI.
  90. if (ri_init(&device->ri, &device->bus)) {
  91. debug("create_device: Failed to initialize the RI.\n");
  92. return NULL;
  93. }
  94.  
  95. // Initialize the SI.
  96. if (si_init(&device->si, &device->bus, pifrom->ptr,
  97. cart->ptr, dd_variant, eeprom->ptr, eeprom->size,
  98. controller)) {
  99. debug("create_device: Failed to initialize the SI.\n");
  100. return NULL;
  101. }
  102.  
  103. // Initialize the VI.
  104. if (vi_init(&device->vi, &device->bus, no_video)) {
  105. debug("create_device: Failed to initialize the VI.\n");
  106. return NULL;
  107. }
  108.  
  109. // Initialize the RDP.
  110. if (rdp_init(&device->rdp, &device->bus)) {
  111. debug("create_device: Failed to initialize the RDP.\n");
  112. return NULL;
  113. }
  114.  
  115. // Initialize the RSP.
  116. if (rsp_init(&device->rsp, &device->bus)) {
  117. debug("create_device: Failed to initialize the RSP.\n");
  118. return NULL;
  119. }
  120.  
  121. // Initialize the VR4300.
  122. if (vr4300_init(&device->vr4300, &device->bus)) {
  123. debug("create_device: Failed to initialize the VR4300.\n");
  124. return NULL;
  125. }
  126.  
  127. angrylion_rdp_init(device);
  128. return device;
  129. }
  130.  
  131. // Cleans up memory allocated for the device.
  132. void device_destroy(struct cen64_device *device) {
  133. rsp_destroy(&device->rsp);
  134. }
  135.  
  136. // Called when we should (probably?) leave simulation.
  137. // After calling this function, we return to device_runmode_*.
  138. void device_exit(struct bus_controller *bus) {
  139. longjmp(bus->unwind_data, 1);
  140. }
  141.  
  142. // Create a device and proceed to the main loop.
  143. void device_run(struct cen64_device *device) {
  144. fpu_state_t saved_fpu_state;
  145. char vendor[13];
  146.  
  147. // TODO: Preserve host registers pinned to the device.
  148. saved_fpu_state = fpu_get_state();
  149. vr4300_cp1_init(&device->vr4300);
  150. rsp_late_init(&device->rsp);
  151.  
  152. // Set thread affinities for Intel CPUs.
  153. cen64_cpuid_get_vendor(vendor);
  154.  
  155. // Spin the device until we return (from setjmp).
  156. if (unlikely(device->debug_sfd > 0))
  157. device_debug_spin(device);
  158.  
  159. else if (device->multithread)
  160. device_multithread_spin(device);
  161.  
  162. else
  163. //device_spin(device);
  164. device_unthreaded_spin(device);
  165.  
  166. // TODO: Restore host registers that were pinned.
  167. fpu_set_state(saved_fpu_state);
  168. }
  169.  
  170. CEN64_THREAD_RETURN_TYPE run_rcp_thread(void *opaque) {
  171. struct cen64_device *device = (struct cen64_device *) opaque;
  172.  
  173. if (setjmp(device->bus.unwind_data))
  174. return CEN64_THREAD_RETURN_VAL;
  175.  
  176. while (likely(device->running)) {
  177. unsigned i, j;
  178.  
  179. #if 0
  180. for (i = 0; i < 6250 / 5; i++) {
  181. for (j = 0; j < 5; j++) {
  182. rsp_cycle(&device->rsp);
  183. vi_cycle(&device->vi);
  184. }
  185.  
  186. rsp_cycle(&device->rsp);
  187. }
  188. #else
  189. for (i = 0; i < (6250 / 5) * (5+1); i++) {
  190. //for (i = 0; i < (6250 / 5) * 3; i++) {
  191. rsp_cycle(&device->rsp);
  192. }
  193. for (i = 0; i < (6250 / 5) * (5); i++) {
  194. vi_cycle(&device->vi);
  195. }
  196. #endif
  197.  
  198. // Sync up with the VR4300 and RDP threads.
  199. cen64_mutex_lock(&device->sync_mutex);
  200.  
  201. if (!device->other_thread_is_waiting) {
  202. if (!device->rsp.rdp_has_pending_dl) {
  203. cen64_mutex_lock(&device->rdp.rdp_mutex);
  204.  
  205. while (device->rdp.remaining_length)
  206. cen64_cv_wait(&device->rdp.rdp_sync_signal, &device->rdp.rdp_mutex);
  207.  
  208. cen64_mutex_unlock(&device->rdp.rdp_mutex);
  209. }
  210.  
  211. device->rsp.rdp_has_pending_dl--;
  212. device->other_thread_is_waiting = true;
  213. cen64_cv_wait(&device->sync_cv, &device->sync_mutex);
  214. cen64_mutex_unlock(&device->sync_mutex);
  215. }
  216.  
  217. else {
  218. device->other_thread_is_waiting = false;
  219. cen64_mutex_unlock(&device->sync_mutex);
  220. cen64_cv_signal(&device->sync_cv);
  221.  
  222. if (!device->rsp.rdp_has_pending_dl) {
  223. cen64_mutex_lock(&device->rdp.rdp_mutex);
  224.  
  225. while (device->rdp.remaining_length)
  226. cen64_cv_wait(&device->rdp.rdp_sync_signal, &device->rdp.rdp_mutex);
  227.  
  228. cen64_mutex_unlock(&device->rdp.rdp_mutex);
  229. }
  230.  
  231. device->rsp.rdp_has_pending_dl--;
  232. }
  233. }
  234.  
  235. return CEN64_THREAD_RETURN_VAL;
  236. }
  237.  
  238. CEN64_THREAD_RETURN_TYPE run_vr4300_thread(void *opaque) {
  239. struct cen64_device *device = (struct cen64_device *) opaque;
  240.  
  241. while (likely(device->running)) {
  242. unsigned i, j;
  243.  
  244. #if 0
  245. for (i = 0; i < 6250 / 2; i++) {
  246. for (j = 0; j < 2; j++) {
  247. ai_cycle(&device->ai);
  248. pi_cycle(&device->pi);
  249. }
  250.  
  251. for (j = 0; j < 3; j++)
  252. vr4300_cycle(&device->vr4300);
  253. }
  254. #else
  255. for (i = 0; i < (6250 / 2) * 2; i++) {
  256. ai_cycle(&device->ai);
  257. }
  258. for (i = 0; i < (6250 / 2) * 2; i++) {
  259. pi_cycle(&device->pi);
  260. }
  261. for (i = 0; i < (6250 / 2) * 3; i++) {
  262. vr4300_cycle(&device->vr4300);
  263. }
  264. #endif
  265.  
  266. // Sync up with the RCP thread.
  267. cen64_mutex_lock(&device->sync_mutex);
  268.  
  269. if (!device->other_thread_is_waiting) {
  270. device->other_thread_is_waiting = true;
  271. cen64_cv_wait(&device->sync_cv, &device->sync_mutex);
  272. cen64_mutex_unlock(&device->sync_mutex);
  273. }
  274.  
  275. else {
  276. device->other_thread_is_waiting = false;
  277. cen64_mutex_unlock(&device->sync_mutex);
  278. cen64_cv_signal(&device->sync_cv);
  279. }
  280. }
  281.  
  282. return CEN64_THREAD_RETURN_VAL;
  283. }
  284.  
  285. //
  286. // Set affinity of threads to maximize performance.
  287. // There should be at least 3 threads, possibly 4:
  288. //
  289. // 0: device/vr4300 thread
  290. // 1: os thread
  291. // 2: rdp thread
  292. // 3: (if present) rcp thread
  293. //
  294. cen64_cold static void device_schedule_threads(
  295. unsigned num_threads, cen64_thread **threads) {
  296.  
  297. cen64_thread_setaffinity(threads[0], 1 << 0);
  298. cen64_thread_setaffinity(threads[1], 1 << 1);
  299. cen64_thread_setaffinity(threads[2], 1 << 2);
  300.  
  301. if (num_threads > 3)
  302. cen64_thread_setaffinity(threads[3], 1 << 3);
  303. }
  304.  
  305. // Continually cycles the device until setjmp returns.
  306. int device_multithread_spin(struct cen64_device *device) {
  307. cen64_thread *device_threads[4];
  308. device->other_thread_is_waiting = false;
  309.  
  310. if (cen64_mutex_create(&device->sync_mutex)) {
  311. printf("Failed to create the synchronization mutex.\n");
  312. return 1;
  313. }
  314.  
  315. if (cen64_cv_create(&device->sync_cv)) {
  316. printf("Failed to create the synchronization CV.\n");
  317. cen64_mutex_destroy(&device->sync_mutex);
  318. return 1;
  319. }
  320.  
  321. if (cen64_thread_create(&device->vr4300_thread, run_vr4300_thread, device)) {
  322. printf("Failed to create the VR4300 thread.\n");
  323. cen64_cv_destroy(&device->sync_cv);
  324. cen64_mutex_destroy(&device->sync_mutex);
  325. return 1;
  326. }
  327.  
  328. device_threads[0] = &device->vr4300_thread;
  329. device_threads[1] = &device->os_thread;
  330. device_threads[2] = &device->rdp.rdp_thread;
  331. device_threads[3] = &device->device_thread;
  332.  
  333. device_schedule_threads(4, device_threads);
  334.  
  335. run_rcp_thread(device);
  336.  
  337. cen64_thread_join(&device->vr4300_thread);
  338. cen64_cv_destroy(&device->sync_cv);
  339. cen64_mutex_destroy(&device->sync_mutex);
  340. return 0;
  341. }
  342.  
  343. // Continually cycles the device until setjmp returns.
  344. int device_spin(struct cen64_device *device) {
  345. cen64_thread *device_threads[3];
  346.  
  347. if (setjmp(device->bus.unwind_data))
  348. return 1;
  349.  
  350. device_threads[0] = &device->device_thread;
  351. device_threads[1] = &device->os_thread;
  352. device_threads[2] = &device->rdp.rdp_thread;
  353.  
  354. device_schedule_threads(3, device_threads);
  355.  
  356. while (likely(device->running)) {
  357. unsigned i, j;
  358.  
  359. #if 1
  360. for (i = 0; i < 6250 / 10; i++) {
  361. for (j = 0; j < 10; j++) {
  362. vr4300_cycle(&device->vr4300);
  363. rsp_cycle(&device->rsp);
  364. ai_cycle(&device->ai);
  365. pi_cycle(&device->pi);
  366. vi_cycle(&device->vi);
  367. }
  368.  
  369. for (j = 0; j < 2; j++)
  370. rsp_cycle(&device->rsp);
  371.  
  372. for (j = 0; j < 5; j++)
  373. vr4300_cycle(&device->vr4300);
  374. }
  375.  
  376. // Sync up with the RDP thread.
  377. if (!device->rsp.rdp_has_pending_dl) {
  378. cen64_mutex_lock(&device->rdp.rdp_mutex);
  379.  
  380. while (device->rdp.remaining_length)
  381. cen64_cv_wait(&device->rdp.rdp_sync_signal, &device->rdp.rdp_mutex);
  382.  
  383. cen64_mutex_unlock(&device->rdp.rdp_mutex);
  384. }
  385.  
  386. device->rsp.rdp_has_pending_dl--;
  387. }
  388. #else
  389. for (i = 0; i < (6250 / 10) * (10+5); i++) {
  390. vr4300_cycle(&device->vr4300);
  391. }
  392. for (i = 0; i < (6250 / 10) * (10+2); i++) {
  393. rsp_cycle(&device->rsp);
  394. }
  395. for (i = 0; i < (6250 / 10) * (10); i++) {
  396. ai_cycle(&device->ai);
  397. }
  398. for (i = 0; i < (6250 / 10) * (10); i++) {
  399. pi_cycle(&device->pi);
  400. }
  401. for (i = 0; i < (6250 / 10) * (10); i++) {
  402. vi_cycle(&device->vi);
  403. }
  404.  
  405. // Sync up with the RDP thread.
  406. if (!device->rsp.rdp_has_pending_dl) {
  407. cen64_mutex_lock(&device->rdp.rdp_mutex);
  408.  
  409. while (device->rdp.remaining_length)
  410. cen64_cv_wait(&device->rdp.rdp_sync_signal, &device->rdp.rdp_mutex);
  411.  
  412. cen64_mutex_unlock(&device->rdp.rdp_mutex);
  413. }
  414.  
  415. device->rsp.rdp_has_pending_dl--;
  416. }
  417. #endif
  418.  
  419. return 0;
  420. }
  421.  
  422. // Continually cycles the device until setjmp returns.
  423. int device_debug_spin(struct cen64_device *device) {
  424. struct vr4300_stats vr4300_stats;
  425.  
  426. // Prepare stats, set a breakpoint @ VR4300 IPL vector.
  427. memset(&vr4300_stats, 0, sizeof(vr4300_stats));
  428. netapi_debug_wait(device->debug_sfd, device);
  429.  
  430. if (setjmp(device->bus.unwind_data))
  431. return 1;
  432.  
  433. while (likely(device->running)) {
  434. unsigned i;
  435.  
  436. for (i = 0; i < 10; i++) {
  437. vr4300_cycle(&device->vr4300);
  438. rsp_cycle(&device->rsp);
  439. ai_cycle(&device->ai);
  440. pi_cycle(&device->pi);
  441. vi_cycle(&device->vi);
  442.  
  443. vr4300_cycle_extra(&device->vr4300, &vr4300_stats);
  444.  
  445. }
  446.  
  447. for (i = 0; i < 2; i++)
  448. rsp_cycle(&device->rsp);
  449.  
  450. for (i = 0; i < 5; i++) {
  451. vr4300_cycle(&device->vr4300);
  452. vr4300_cycle_extra(&device->vr4300, &vr4300_stats);
  453. }
  454. }
  455.  
  456. return 0;
  457. }
  458.  
  459. int device_unthreaded_spin(struct cen64_device *device) {
  460. if (setjmp(device->bus.unwind_data))
  461. return 1;
  462.  
  463. while (likely(device->running)) {
  464. unsigned i;
  465.  
  466. for (i = 0; i < (6250/10) * (10+5); i++) {
  467. vr4300_cycle(&device->vr4300);
  468. }
  469. for (i = 0; i < (6250/10) * (10+2); i++) {
  470. //for (i = 0; i < (6250/10) * (6); i++) {
  471. rsp_cycle(&device->rsp);
  472. }
  473. for (i = 0; i < (6250/10) * (10); i++) {
  474. ai_cycle(&device->ai);
  475. }
  476. for (i = 0; i < (6250/10) * (10); i++) {
  477. pi_cycle(&device->pi);
  478. }
  479. for (i = 0; i < (6250/10) * (10); i++) {
  480. vi_cycle(&device->vi);
  481. }
  482. }
  483.  
  484. return 0;
  485. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement