Advertisement
Guest User

Untitled

a guest
Dec 4th, 2016
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.98 KB | None | 0 0
  1. # syscall constants
  2. PRINT_STRING = 4
  3. PRINT_CHAR = 11
  4. PRINT_INT = 1
  5.  
  6. # memory-mapped I/O
  7. VELOCITY = 0xffff0010
  8. ANGLE = 0xffff0014
  9. ANGLE_CONTROL = 0xffff0018
  10.  
  11. BOT_X = 0xffff0020
  12. BOT_Y = 0xffff0024
  13.  
  14. TIMER = 0xffff001c
  15.  
  16. TILE_SCAN = 0xffff0024
  17. HARVEST_TILE = 0xffff0020
  18.  
  19. GET_FIRE_LOC = 0xffff0028
  20. PUT_OUT_FIRE = 0xffff0040
  21.  
  22. PRINT_INT_ADDR = 0xffff0080
  23. PRINT_FLOAT_ADDR = 0xffff0084
  24. PRINT_HEX_ADDR = 0xffff0088
  25.  
  26. # interrupt constants
  27. BONK_MASK = 0x1000
  28. BONK_ACK = 0xffff0060
  29.  
  30. TIMER_MASK = 0x8000
  31. TIMER_ACK = 0xffff006c
  32.  
  33. ON_FIRE_MASK = 0x400
  34. ON_FIRE_ACK = 0xffff0050
  35.  
  36. # a macro for a good velocity for the bot
  37. A_GOOD_SPEED = 10
  38.  
  39. .data
  40.  
  41. .align 2
  42.  
  43. tile_data:
  44. .space 1600
  45.  
  46. .text
  47. #------------------------------------------------------------------------START
  48. main:
  49. #Tell the bot to stop moving
  50. sw $0, VELOCITY
  51. #First initialize shared data structures (set up the queue)
  52. la $t0, fire_queue_head_idx
  53. sw $0, 0($t0) #head_idx= 0
  54. la $t0 fire_queue_tail_idx
  55. sw $0, 0($t0) #tail_idx = 0
  56.  
  57. # Next enable fire interrupts
  58. li $t0, ON_FIRE_MASK
  59. or $t0, $t0, 1 #Global interrupt enable
  60. mtc0 $t0, $12
  61.  
  62. #Now just poll the fire_queue and start putting out fires
  63. la $s0, fire_queue_x
  64. la $s1, fire_queue_y
  65.  
  66. fire_loop:
  67. la $s2, fire_queue_head_idx
  68. lw $s3, 0($s2) #s2 = &head_idx
  69.  
  70. la $s4, fire_queue_tail_idx
  71. lw $s4, 0($s4)
  72.  
  73. bge $s3, $s4, fire_loop #If the queue is empty, keep waiting for a fire_interrupt
  74.  
  75. #--- If the queue is non_empty pull the x and y coordinates at fire_queue_x[head_idx] and fire_queue_y[head_idx]----
  76. mul $t2, $s3, 4
  77. add $t0, $t2, $s0
  78. add $t1, $t2, $s1 #t0 = &target_x, t1 = &target_y
  79. #--- Save the $a registers and then load arguments for call to move_to_tile----
  80. sw $a0, -4($sp)
  81. sw $a1, -8($sp)
  82. sub $sp, $sp, 8
  83.  
  84. lw $a0, 0($t1) #t0 = fire_queue_x[head_idx] (row)
  85. lw $a1, 0($t0) #t1 = fire_queue_y[head_idx](column)
  86. jal move_to_tile
  87.  
  88. move $t2, $a0
  89. move $t3, $a1
  90. lw $a1, 0($sp)
  91. lw $a0, 4($sp)
  92. addi $sp, $sp, 8
  93.  
  94. #----we're now on a tile that should be on fire, check if we can salvage the plant, if so put it out----
  95. la $t1, tile_data
  96. sw $t1, TILE_SCAN
  97. mul $t2, $t2, 10
  98. add $t2, $t2, $t3 #t2 has linear index of tile tile_data
  99. la $t3, tile_data
  100. mul $t2, $t2, 16
  101. add $t3, $t3, $t2 # t3 has the address of the Tile_info struct we want
  102. lw $t3, 0($t3) # t3 has the state of the current struct
  103. beq $t3, 0, ignore # if state is 0, it's too late to save the plant
  104. lw $t3, PUT_OUT_FIRE
  105. #----t2 contains whether attempt was a success or not if we want to requeue the fire -----
  106. ignore:
  107. addi $s3, $s3, 1
  108. sw $s3, 0($s2) #head_idx++
  109.  
  110. j fire_loop #infinite fire seeking loop
  111.  
  112. jr $ra
  113. #--------------------------------------------------------------------------END
  114.  
  115.  
  116.  
  117. # void move_to_tile(int row, int column)-----------------------------------START
  118. move_to_tile:
  119. sw $s0, -4($sp)
  120. sw $s1, -8($sp)
  121. sw $s2, -12($sp)
  122. sw $s3, -16($sp)
  123. sub $sp, $sp, 16
  124. #-------------------
  125.  
  126. # first get SPIMbot's current coordinates
  127. lw $s0, BOT_Y #s0 = curr_y
  128. lw $s1, BOT_X #s1 = curr_x
  129. #now load target coordinates
  130. move $s2,$a0
  131. mul $s2, $s2, 30
  132. addi $s2, $s2, 15 #s2 = target_y
  133.  
  134. move $s3,$a1
  135. mul $s3, $s3, 30
  136. addi $s3, $s3, 15 #s3 = target_x
  137.  
  138. #--------now move in the y direction until you hit target_y----
  139.  
  140. # here we are moving up
  141. li $t0, -90
  142. #do a check for which direction we need to move
  143. bge $s0, $s2, set_velocity_y
  144. #turn SPIMbot to face down
  145. li $t0, 90
  146. set_velocity_y:
  147. sw $t0, ANGLE
  148. li $t1, 1
  149. sw $t1, ANGLE_CONTROL
  150. # spim bot is now facing in the required direction
  151. li $t0, A_GOOD_SPEED
  152. sw $t0, VELOCITY
  153. wait_till_target_y:
  154. lw $t0, BOT_Y
  155. bne $t0, $s2, wait_till_target_y
  156. sw $0, VELOCITY
  157.  
  158. #------ Now move in the x direction until we get where we need to go
  159.  
  160. #intialize SPIMbot to face -x
  161. li $t0, 180
  162. #do a check for which direction we need to move
  163. bge $s1, $s3, set_velocity_x
  164. #turn SPIMbot to face +x
  165. li $t0, 0
  166. set_velocity_x:
  167. sw $t0, ANGLE
  168. li $t1, 1
  169. sw $t1, ANGLE_CONTROL
  170. # spim bot is now facing in the required direction
  171. li $t0, A_GOOD_SPEED
  172. sw $t0, VELOCITY
  173. wait_till_target_x:
  174. lw $t0, BOT_X
  175. bne $t0, $s3, wait_till_target_x
  176. sw $0, VELOCITY
  177.  
  178. #-------Spim bot is at the required place, now we just return ----
  179.  
  180. lw $s3, 0($sp)
  181. lw $s2, 4($sp)
  182. lw $s1, 8($sp)
  183. lw $s0, 12($sp)
  184. addi $sp, $sp, 16
  185. jr $ra
  186. #------------------------------------------------------------------------END
  187.  
  188. .data #this is data shared by the interrupt handler and the user program (driver??)
  189.  
  190. fire_queue_head_idx: .space 4
  191. fire_queue_x:.space 400
  192. fire_queue_y:.space 400
  193. fire_queue_tail_idx: .space 4
  194.  
  195. .kdata
  196. chunkIH: .space 16 # space here based on how many registers i need, because i need to save and restore all
  197. unhandled_str: .asciiz "Unhandled interrupt type\n"
  198.  
  199. .ktext 0x80000180
  200. #------------------------------------------------------------------------START
  201. interrupt_handler:
  202. la $k0, chunkIH
  203. .set noat # this allows me to access $at directly
  204. sw $at, 0($k0)
  205. .set at
  206.  
  207. sw $a0, 4($k0) #save a0 and a1
  208. sw $a1, 8($k0)
  209. sw $v0, 12($k0)
  210.  
  211. #----we don't have any exceptions but if we did we would check for them here -----
  212. interrupt_dispatch:
  213.  
  214. mfc0 $k0, $13 # move the cause register into k0
  215. beq $k0, $0, done # if the cause_register is 0, interrupts were handled and we're done
  216.  
  217. #----otherwise we have several dispatch checks for every interrupt it could be ---
  218.  
  219. and $a0, $k0, ON_FIRE_MASK
  220. bne $a0, $0, fire_interrupt #If a fire interrupt was triggered, handle it
  221.  
  222. #----Put more interrupt checks above this --------------------------
  223.  
  224. li $v0, PRINT_STRING
  225. la $a0, unhandled_str
  226. syscall
  227. j done
  228.  
  229. fire_interrupt:
  230. lw $a0, GET_FIRE_LOC # get the location of fire as a 32-bit int
  231. sw $a1, ON_FIRE_ACK # acknowledge fire interrupt to allow more (send_eoi)
  232. # ----Get flaming tile coordinates -------
  233. srl $k0, $a0, 16 #shift out the y bits to get x index
  234. and $k1, $a0, 0xffff #mask the top 16 bits to get the y index
  235. # --- Now we have the row and column of the fire, put it on the fire_queue ---
  236. la $a0, fire_queue_tail_idx
  237. lw $v0, 0($a0) #a0 = tail_idx
  238. addi $a1, $v0, 1
  239. sw $a1, 0($a0) #tail_idx++
  240. mul $a0, $v0, 4
  241.  
  242. la $a1, fire_queue_x
  243. add $a1, $a1, $a0
  244. sw $k0, 0($a1) #fire_queue_x[(old)tail_idx] = target_x
  245.  
  246. la $a1, fire_queue_y
  247. add $a1, $a1, $a0
  248. sw $k1, 0($a1) #fire_queue_y[(old) tail_idx] = target_y
  249.  
  250. j interrupt_dispatch
  251. timer_interrupt:
  252. #do nothing because we don't have timer interrupts
  253. done:
  254. la $k0, chunkIH
  255. lw $a0, 4($k0) # Restore saved registers
  256. lw $a1, 8($k0)
  257. lw $v0, 12($k0)
  258. .set noat
  259. lw $at, 0($k0) # Restore $at
  260. .set at
  261. eret
  262. #---------------------------------------------------------------------------END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement