Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2018
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.85 KB | None | 0 0
  1. #include <stdio.h> // for stderr
  2. #include <stdlib.h> // for exit()
  3. #include "types.h"
  4. #include "utils.h"
  5. #include "riscv.h"
  6.  
  7. void execute_rtype(Instruction, Processor *);
  8. void execute_itype_except_load(Instruction, Processor *);
  9. void execute_branch(Instruction, Processor *);
  10. void execute_jal(Instruction, Processor *);
  11. void execute_load(Instruction, Processor *, Byte *);
  12. void execute_store(Instruction, Processor *, Byte *);
  13. void execute_ecall(Processor *, Byte *);
  14. void execute_lui(Instruction, Processor *);
  15.  
  16. void execute_instruction(uint32_t instruction_bits, Processor *processor,Byte *memory) {
  17. Instruction instruction = parse_instruction(instruction_bits);
  18. switch(instruction.opcode) {
  19. case 0x33:
  20. execute_rtype(instruction, processor);
  21. break;
  22. case 0x13:
  23. execute_itype_except_load(instruction, processor);
  24. break;
  25. case 0x73:
  26. execute_ecall(processor, memory);
  27. break;
  28. case 0x63:
  29. execute_branch(instruction, processor);
  30. break;
  31. case 0x6F:
  32. execute_jal(instruction, processor);
  33. break;
  34. case 0x23:
  35. execute_store(instruction, processor, memory);
  36. break;
  37. case 0x03:
  38. execute_load(instruction, processor, memory);
  39. break;
  40. case 0x37:
  41. execute_lui(instruction, processor);
  42. break;
  43. default: // undefined opcode
  44. handle_invalid_instruction(instruction);
  45. exit(-1);
  46. break;
  47. }
  48. }
  49.  
  50. void execute_rtype(Instruction instruction, Processor *processor) {
  51. switch (instruction.rtype.funct3){
  52. case 0x0:
  53. switch (instruction.rtype.funct7) {
  54. case 0x0:
  55. // Add
  56. int add1 = processor->R[instruction.rtype.rs1];
  57. int add2 = processor->R[instruction.rtype.rs2];
  58. processor->R[instruction.rtype.rd] = add1 + add2;
  59. processor->PC += 4;
  60. break;
  61. case 0x1:
  62. // Mul
  63. int mul1 = processor->R[instruction.rtype.rs1];
  64. int mul2 = processor->R[instruction.rtype.rs2];
  65. processor->R[instruction.rtype.rd] = mul1 * mul2;
  66. processor->PC += 4;
  67. break;
  68. case 0x20:
  69. // Sub
  70. int sub1 = processor->R[instruction.rtype.rs1];
  71. int sub2 = processor->R[instruction.rtype.rs2];
  72. processor->R[instruction.rtype.rd] = sub1 - sub2;
  73. processor->PC += 4;
  74. break;
  75. default:
  76. handle_invalid_instruction(instruction);
  77. exit(-1);
  78. break;
  79. }
  80. break;
  81. case 0x1:
  82. switch (instruction.rtype.funct7) {
  83. case 0x0:
  84. // SLL
  85. int sll1 = processor->R[instruction.rtype.rs1];
  86. int sll2 = processor->R[instruction.rtype.rs2];
  87. processor->R[instruction.rtype.rd] = sll1 << sll2;
  88. processor->PC += 4;
  89. break;
  90. case 0x1:
  91. // MULH
  92. int mulh1 = processor->R[instruction.rtype.rs1];
  93. int mulh2 = processor->R[instruction.rtype.rs2];
  94. int result = mulh1 * mulh2;
  95. processor->R[instruction.rtype.rd] = result >> 32;
  96. processor->PC += 4;
  97. break;
  98. }
  99. break;
  100. case 0x2:
  101. // SLT
  102. int slt1 = processor->R[instruction.rtype.rs1];
  103. int slt2 = processor->R[instruction.rtype.rs2];
  104. if (slt1 < slt2) {
  105. processor->R[instruction.rtype.rd] = 1;
  106. } else {
  107. processor->R[instruction.rtype.rd] = 0;
  108. }
  109. processor->PC += 4;
  110. break;
  111. case 0x4:
  112. switch (instruction.rtype.funct7) {
  113. case 0x0:
  114. // XOR
  115. int xor1 = processor->R[instruction.rtype.rs1];
  116. int xor2 = processor->R[instruction.rtype.rs2];
  117. processor->R[instruction.rtype.rd] = xor1 ^ xor2;
  118. processor->PC += 4;
  119. break;
  120. case 0x1:
  121. // DIV
  122. int div1 = processor->R[instruction.rtype.rs1];
  123. int div2 = processor->R[instruction.rtype.rs2];
  124. processor->R[instruction.rtype.rd] = div1 / div2;
  125. processor->PC += 4;
  126. break;
  127. default:
  128. handle_invalid_instruction(instruction);
  129. exit(-1);
  130. break;
  131. }
  132. break;
  133. case 0x5:
  134. switch (instruction.rtype.funct7) {
  135. case 0x0:
  136. // SRL
  137. int srl1 = processor->R[instruction.rtype.rs1];
  138. int srl2 = processor->R[instruction.rtype.rs2];
  139. processor->R[instruction.rtype.rd] = srl1 >> srl2;
  140. processor->PC += 4;
  141. break;
  142. case 0x20:
  143. // SRA
  144. int sra1 = processor->R[instruction.rtype.rs1];
  145. int sra2 = processor->R[instruction.rtype.rs2];
  146. processor->R[instruction.rtype.rd] = sra1 >> sra2;
  147. processor->PC += 4;
  148. break;
  149. default:
  150. handle_invalid_instruction(instruction);
  151. exit(-1);
  152. break;
  153. }
  154. break;
  155. case 0x6:
  156. switch (instruction.rtype.funct7) {
  157. case 0x0:
  158. // OR
  159. int or1 = processor->R[instruction.rtype.rs1];
  160. int or2 = processor->R[instruction.rtype.rs2];
  161. processor->R[instruction.rtype.rd] = or1 | or2;
  162. processor->PC += 4;
  163. break;
  164. case 0x1:
  165. // REM
  166. int rem1 = processor->R[instruction.rtype.rs1];
  167. int rem2 = processor->R[instruction.rtype.rs2];
  168. processor->R[instruction.rtype.rd] = rem1 % rem2;
  169. processor->PC += 4;
  170. break;
  171. default:
  172. handle_invalid_instruction(instruction);
  173. exit(-1);
  174. break;
  175. }
  176. break;
  177. case 0x7:
  178. // AND
  179. int and1 = processor->R[instruction.rtype.rs1];
  180. int and2 = processor->R[instruction.rtype.rs2];
  181. processor->R[instruction.rtype.rd] = and1 | and2;
  182. processor->PC += 4;
  183. break;
  184. default:
  185. handle_invalid_instruction(instruction);
  186. exit(-1);
  187. break;
  188. }
  189. }
  190.  
  191. void execute_itype_except_load(Instruction instruction, Processor *processor) {
  192. int shiftOp;
  193. switch (instruction.itype.funct3) {
  194. case 0x0:
  195. // ADDI
  196. int addi1 = processor->R[instruction.itype.rs1];
  197. int addi2 = sign_extend_number(instruction.itype.imm, 12);
  198. processor->R[instruction.itype.rd] = addi1 + addi2;
  199. processor->PC += 4;
  200. break;
  201. case 0x1:
  202. // SLLI
  203. int slli1 = processor->R[instruction.itype.rs1];
  204. int slli2 = instruction.itype.imm;
  205. processor->R[instruction.itype.rd] = slli1 << slli2;
  206. processor->PC += 4;
  207. break;
  208. case 0x2:
  209. // STLI
  210. int stli1 = processor->R[instruction.itype.rs1];
  211. int stli2 = sign_extend_number(instruction.itype.imm, 12);
  212. if (stli1 < stli2) {
  213. processor->R[instruction.itype.rd] = 1;
  214. } else {
  215. processor->R[instruction.itype.rd] = 0;
  216. }
  217. processor->PC += 4;
  218. break;
  219. case 0x4:
  220. // XORI
  221. int xori1 = processor->R[instruction.itype.rs1];
  222. int xori2 = sign_extend_number(instruction.itype.imm, 12);
  223. processor->R[instruction.itype.rd] = xori1 ^ xori2;
  224. processor->PC += 4;
  225. break;
  226. case 0x5:
  227. // Shift Right (You must handle both logical and arithmetic)
  228. switch (instruction.itype.imm >> 5) {
  229. case 0x00:
  230. int srli1 = processor->R[instruction.itype.rs1];
  231. int srli2 = instruction.itype.imm;
  232. processor->R[instruction.itype.rd] = srli1 >> srli2;
  233. processor->PC += 4;
  234. break;
  235. case 0x20:
  236. int srai1 = processor->R[instruction.itype.rs1];
  237. int srai2 = instruction.itype.imm;
  238. processor->R[instruction.itype.rd] = srai1 >> srai2;
  239. processor->PC += 4;
  240. break;
  241. default:
  242. handle_invalid_instruction(instruction);
  243. break;
  244. }
  245. case 0x6:
  246. // ORI
  247. int ori1 = processor->R[instruction.itype.rs1];
  248. int ori2 = sign_extend_number(instruction.itype.imm, 12);
  249. processor->R[instruction.itype.rd] = ori1 | ori2;
  250. processor->PC += 4;
  251. break;
  252. case 0x7:
  253. // ANDI
  254. int andi1 = processor->R[instruction.itype.rs1];
  255. int andi2 = sign_extend_number(instruction.itype.imm, 12);
  256. processor->R[instruction.itype.rd] = andi1 & andi2;
  257. processor->PC += 4;
  258. break;
  259. default:
  260. handle_invalid_instruction(instruction);
  261. break;
  262. }
  263. }
  264.  
  265. void execute_ecall(Processor *p, Byte *memory) {
  266. Register i;
  267.  
  268. // syscall number is given by a0 (x10)
  269. // argument is given by a1
  270. switch(p->R[10]) {
  271. case 1: // print an integer
  272. printf("%d",p->R[11]);
  273. p->PC += 4;
  274. break;
  275. case 4: // print a string
  276. for(i=p->R[11];i<MEMORY_SPACE && load(memory,i,LENGTH_BYTE);i++) {
  277. printf("%c",load(memory,i,LENGTH_BYTE));
  278. }
  279. p->PC += 4;
  280. break;
  281. case 10: // exit
  282. printf("exiting the simulator\n");
  283. p->PC += 4;
  284. exit(0);
  285. break;
  286. case 11: // print a character
  287. printf("%c",p->R[11]);
  288. p->PC += 4;
  289. break;
  290. default: // undefined ecall
  291. printf("Illegal ecall number %d\n", p->R[10]);
  292. exit(-1);
  293. break;
  294. }
  295. }
  296.  
  297. void execute_branch(Instruction instruction, Processor *processor) {
  298. switch (instruction.sbtype.funct3) {
  299. case 0x0:
  300. // BEQ
  301. int brn0 = processor->PC + sign_extend_number(get_branch_offset(instruction), 13);
  302. int eq10 = processor->R[instruction.sbtype.rs1];
  303. int eq20 = processor->R[instruction.sbtype.rs2];
  304. if (eq10 == eq20) {
  305. processor->PC = brn0;
  306. } else {
  307. processor->PC += 4;
  308. }
  309. break;
  310. case 0x1:
  311. // BNE
  312. int brn1 = processor->PC + sign_extend_number(get_branch_offset(instruction), 13);
  313. int eq11 = processor->R[instruction.sbtype.rs1];
  314. int eq21 = processor->R[instruction.sbtype.rs2];
  315. if (eq11 != eq21) {
  316. processor->PC = brn1;
  317. } else {
  318. processor->PC += 4;
  319. }
  320. break;
  321. default:
  322. handle_invalid_instruction(instruction);
  323. exit(-1);
  324. break;
  325. }
  326. }
  327.  
  328. void execute_load(Instruction instruction, Processor *processor, Byte *memory) {
  329. switch (instruction.itype.funct3) {
  330. case 0x0:
  331. // LB
  332. processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_BYTE);
  333. //processor->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_BYTE), 8);
  334. processor->PC += 4;
  335. break;
  336. case 0x1:
  337. // LH
  338. processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_HALF_WORD);
  339. //processor->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_HALF_WORD), 16);
  340. processor->PC += 4;
  341. break;
  342. case 0x2:
  343. // LW
  344. processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_WORD);
  345. //processor->R[instruction.itype.rd] = sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + instruction.itype.imm, LENGTH_WORD), 32);
  346. processor->PC += 4;
  347. break;
  348. default:
  349. handle_invalid_instruction(instruction);
  350. break;
  351. }
  352. }
  353.  
  354. void execute_store(Instruction instruction, Processor *processor, Byte *memory) {
  355. switch (instruction.stype.funct3) {
  356. case 0x0:
  357. // SB
  358. store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_BYTE, processor->R[instruction.stype.rs2]);
  359. processor->PC += 4;
  360. break;
  361. case 0x1:
  362. // SH
  363. store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_HALF_WORD, processor->R[instruction.stype.rs2]);
  364. processor->PC += 4;
  365. break;
  366. case 0x2:
  367. // SW
  368. store(memory, processor->R[instruction.stype.rs1] + sign_extend_number(get_store_offset(instruction), 12), LENGTH_WORD, processor->R[instruction.stype.rs2]);
  369. processor->PC += 4;
  370. break;
  371. default:
  372. handle_invalid_instruction(instruction);
  373. exit(-1);
  374. break;
  375. }
  376. }
  377.  
  378. void execute_jal(Instruction instruction, Processor *processor) {
  379. /* YOUR CODE HERE */
  380. int nextPC = processor->PC + get_jump_offset(instruction);
  381. processor->R[instruction.ujtype.rd] = processor->PC + 4;
  382. processor->PC = nextPC;
  383. }
  384.  
  385. void execute_lui(Instruction instruction, Processor *processor) {
  386. /* YOUR CODE HERE */
  387. int imm = sign_extend_number(instruction.utype.imm, 32) << 12;
  388. processor->R[instruction.utype.rd] = imm;
  389. processor->PC += 4;
  390. }
  391.  
  392. void store(Byte *memory, Address address, Alignment alignment, Word value) {
  393. /* YOUR CODE HERE */
  394.  
  395. if (alignment == LENGTH_WORD)
  396. *(uint32_t*)(memory + address) = (uint32_t) value;
  397. else if (alignment == LENGTH_HALF_WORD)
  398. *(uint16_t*)(memory + address) = (uint16_t) value;
  399. else if (alignment == LENGTH_BYTE)
  400. *(uint8_t*)(memory + address) = (uint8_t) value;
  401.  
  402. }
  403.  
  404. Word load(Byte *memory, Address address, Alignment alignment) {
  405. /* YOUR CODE HERE */
  406.  
  407. if(((address==0)|((address+alignment)<1) | ((address+alignment)>=MEMORY_SPACE))){exit(-1);}
  408. if((alignment==LENGTH_HALF_WORD && (address %2 !=0))){exit(-1);}
  409. if((alignment==LENGTH_WORD && (address % 4 !=0))){exit(-1);}
  410. switch(alignment){
  411. case LENGTH_BYTE:
  412. return *(Byte*) (memory+address);
  413. case LENGTH_HALF_WORD:
  414. return *(Half*) (memory+address);
  415. default:
  416. return *(Word*) (memory+address);
  417. }
  418.  
  419. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement