testgen.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <stdint.h>
  5. #include <stdbool.h>
  6. #include <string.h>
  7. #include <time.h>
  8. uint32_t create_mask(uint8_t from, uint8_t to)
  9. {
  10. uint32_t r = 0;
  11. for (uint8_t i = from; i <= to; i++)
  12. r |= 1 << i;
  13. return r;
  14. }
  15. uint8_t *allocate_uint_bytes(uint32_t uint)
  16. {
  17. uint8_t *uints = malloc(4);
  18. for (size_t i = 0; i < 4; i++)
  19. uints[3 - i] = (uint & create_mask(i * 8, (i + 1) * 8)) >> (i * 8);
  20. return uints;
  21. }
  22. // little endian
  23. // incoherently unreadable, but does get the job done
  24. char *uint_to_binary_string(uint32_t uint, size_t bytes)
  25. {
  26. char *buf = malloc(33);
  27. uint8_t *uints = allocate_uint_bytes(uint);
  28. for (size_t i = 0; i < bytes; i++)
  29. for (size_t j = 0; j < 8; j++)
  30. buf[i * 8 + j] = (((1 << (7 - j)) & uints[i + 4 - bytes]) > 0) ? '1' : '0';
  31. buf[bytes * 8] = '\0';
  32. //printf("%u\n%x %x %x %x\n%s\n", uint, uints[0], uints[1], uints[2], uints[3], buf);
  33. free(uints);
  34. return buf;
  35. }
  36. char *binary_string_n_bits(char *str, size_t n)
  37. {
  38. size_t i;
  39. for (i = 0; i < n; i++)
  40. str[i] = str[strlen(str) - n + i];
  41. str[i] = '\0';
  42. return str;
  43. }
  44. typedef enum {
  45. LUI = 0, AUIPC, JAL, JALR, BRANCH, LOAD, STORE, OP_IMM, OP, NOP, INVALID, OPCODE_SIZE
  46. } opcode;
  47. typedef enum {
  48. ALU_NOP = 0, ALU_ADD, ALU_SUB, ALU_SLL, ALU_SLT, ALU_SLTU, ALU_XOR, ALU_SRL, ALU_SRA, ALU_OR, ALU_AND, ALU_OPCODE_SIZE
  49. } alu_opcode;
  50. char *alu_opcodes[ALU_OPCODE_SIZE] = {
  51. "ALU_NOP", "ALU_ADD", "ALU_SUB", "ALU_SLL", "ALU_SLT", "ALU_SLTU", "ALU_XOR", "ALU_SRL", "ALU_SRA", "ALU_OR", "ALU_AND"
  52. };
  53. typedef enum {
  54. MEM_B = 0, MEM_BU, MEM_H, MEM_HU, MEM_W, MEMTYPE_SIZE
  55. } memtype;
  56. char *memtypes[MEMTYPE_SIZE] = {
  57. "MEM_B", "MEM_BU", "MEM_H", "MEM_HU", "MEM_W"
  58. };
  59. typedef enum {
  60. BR_NOP = 0, BR_BR, BR_CND, BR_CNDI, BRANCHTYPE_SIZE
  61. } branchtype;
  62. char *branchtypes[BRANCHTYPE_SIZE] = {
  63. "BR_NOP", "BR_BR", "BR_CND", "BR_CNDI"
  64. };
  65. typedef enum {
  66. WBS_ALU = 0, WBS_MEM, WBS_OPC, WBTYPE_SIZE
  67. } wbtype;
  68. char *wbtypes[WBTYPE_SIZE] = {
  69. "WBS_ALU", "WBS_MEM", "WBS_OPC"
  70. };
  71. typedef struct {
  72. // alu op
  73. alu_opcode aluop;
  74. bool alusrc1;
  75. bool alusrc2;
  76. bool alusrc3;
  77. uint8_t rs1;
  78. uint8_t rs2;
  79. uint32_t readdata1;
  80. uint32_t readdata2;
  81. uint32_t imm;
  82. } exec_op_t;
  83. typedef struct {
  84. // mem op
  85. branchtype branch;
  86. bool memread;
  87. bool memwrite;
  88. memtype memtype;
  89. } mem_op_t;
  90. typedef struct {
  91. // wb op
  92. uint8_t rd;
  93. bool write;
  94. wbtype src;
  95. } wb_op_t;
  96. typedef struct {
  97. bool write;
  98. uint8_t reg;
  99. uint32_t data;
  100. } reg_write_t;
  101. typedef struct {
  102. bool stall;
  103. bool flush;
  104. uint16_t pc_in;
  105. // alu op
  106. exec_op_t exec_op;
  107. // mem op
  108. mem_op_t mem_op;
  109. // wb op
  110. wb_op_t wb_op;
  111. // regwrites
  112. reg_write_t mem;
  113. reg_write_t wr;
  114. } input_t;
  115. typedef struct {
  116. uint16_t pc_old_out;
  117. uint16_t pc_new_out;
  118. uint32_t aluresult;
  119. char zero;
  120. uint32_t wrdata;
  121. // alu op
  122. exec_op_t exec_op;
  123. // mem op
  124. mem_op_t mem_op;
  125. // wb op
  126. wb_op_t wb_op;
  127. } output_t;
  128. int main(void) {
  129. FILE *file_output;
  130. FILE *file_input;
  131. file_output = fopen("./testdata/output.txt", "w");
  132. file_input = fopen("./testdata/input.txt", "w");
  133. srand(time(NULL));
  134. int n = 50;
  135. for (size_t i = 0; i < 50; i++) {
  136. // create random input
  137. input_t input;
  138. input.stall = false;
  139. input.flush = false;
  140. input.pc_in = rand();
  141. input.exec_op.aluop = rand() % ALU_OPCODE_SIZE;
  142. input.exec_op.alusrc1 = rand() % 2 ? true : false;
  143. input.exec_op.alusrc2 = rand() % 2 ? true : false;
  144. input.exec_op.alusrc3 = rand() % 2 ? true : false;
  145. input.exec_op.rs1 = 0;
  146. input.exec_op.rs2 = 0;
  147. input.exec_op.readdata1 = rand();
  148. input.exec_op.readdata2 = rand();
  149. input.exec_op.imm = rand();
  150. input.mem_op.branch = rand() % BRANCHTYPE_SIZE;
  151. input.mem_op.memread = rand() % 2 ? true : false;
  152. input.mem_op.memwrite = !input.mem_op.memread;
  153. input.mem_op.memtype = rand() % MEMTYPE_SIZE;
  154. input.wb_op.rd = rand();
  155. input.wb_op.write = rand() % 2 ? true : false;
  156. input.wb_op.src = rand() % WBTYPE_SIZE;
  157. input.mem.write = rand() % 2 ? true : false;
  158. input.mem.reg = rand();
  159. input.mem.data = rand();
  160. input.wr.write = rand() % 2 ? true : false;
  161. input.wr.reg = rand();
  162. input.wr.data = rand();
  163. // pre determined output
  164. output_t output;
  165. output.pc_old_out = input.pc_in;
  166. output.pc_new_out = (input.exec_op.alusrc1 && input.exec_op.alusrc2 && input.exec_op.alusrc3) ? ((input.exec_op.readdata1 & 0b1111111111111111) + (input.exec_op.imm & 0b1111111111111111)) : (input.pc_in + (input.exec_op.alusrc3 ? input.exec_op.imm : 0));
  167. output.wrdata = input.exec_op.readdata2;
  168. //output.exec_op = input.exec_op;
  169. output.exec_op.aluop = input.exec_op.aluop;
  170. output.exec_op.alusrc1 = input.exec_op.alusrc1;
  171. output.exec_op.alusrc2 = input.exec_op.alusrc2;
  172. output.exec_op.alusrc3 = input.exec_op.alusrc3;
  173. output.exec_op.rs1 = input.exec_op.rs1;
  174. output.exec_op.rs2 = input.exec_op.rs2;
  175. output.exec_op.readdata1 = input.exec_op.readdata1;
  176. output.exec_op.readdata2 = input.exec_op.readdata2;
  177. output.exec_op.imm = input.exec_op.imm;
  178. output.mem_op = input.mem_op;
  179. output.wb_op = input.wb_op;
  180. uint32_t alu_in1 = input.exec_op.alusrc1 ? input.pc_in : input.exec_op.readdata1;
  181. uint32_t alu_in2 = input.exec_op.alusrc2 ? input.exec_op.imm : input.exec_op.readdata2;
  182. switch (input.exec_op.aluop) {
  183. case ALU_NOP:
  184. output.aluresult = alu_in2;
  185. break;
  186. case ALU_ADD:
  187. output.aluresult = alu_in1 + alu_in2;
  188. break;
  189. case ALU_SUB:
  190. output.aluresult = alu_in1 - alu_in2;
  191. break;
  192. case ALU_SLL:
  193. output.aluresult = alu_in1 << (alu_in2 & 0b11111);
  194. break;
  195. case ALU_SLT:
  196. output.aluresult = (((int32_t) alu_in1) < ((int32_t) alu_in2)) ? 1 : 0;
  197. break;
  198. case ALU_SLTU:
  199. output.aluresult = (alu_in1 < alu_in2) ? 1 : 0;
  200. break;
  201. case ALU_XOR:
  202. output.aluresult = alu_in1 ^ alu_in2;
  203. break;
  204. case ALU_SRL:
  205. output.aluresult = alu_in1 >> (alu_in2 & 0b11111);
  206. break;
  207. case ALU_SRA:
  208. output.aluresult = (uint32_t) ((int32_t) alu_in1) >> (alu_in2 & 0b11111);
  209. break;
  210. case ALU_OR:
  211. output.aluresult = alu_in1 | alu_in2;
  212. break;
  213. case ALU_AND:
  214. output.aluresult = alu_in1 & alu_in2;
  215. break;
  216. default:
  217. output.aluresult = 0;
  218. break;
  219. }
  220. output.zero = '-';
  221. if (input.exec_op.aluop == ALU_SUB)
  222. output.zero = (alu_in1 == alu_in2) ? '1' : '0';
  223. else if (input.exec_op.aluop == ALU_SLT || input.exec_op.aluop == ALU_SLTU)
  224. output.zero = !((output.aluresult & 1) > 0) ? '1' : '0';
  225. // output results
  226. fprintf(
  227. file_input,
  228. "# test case %zu\n# stall\n%d\n# flush\n%d\n# pc\n%s\n# aluop\n%s\n# alusrc1\n%d\n# alusrc2\n%d\n# alusrc3\n%d\n# rs1\n%s\n# rs2\n%s\n# readdata1\n%s\n# readdata2\n%s\n# imm\n%s\n# branchtype\n%s\n# memread\n%d\n# memwrite\n%d\n# memtype\n%s\n# wb rd\n%s\n# wb write\n%d\n# wb src\n%s\n# reg write mem write\n%d\n# reg write mem reg\n%s\n# reg write mem data\n%s\n# reg write wr write\n%d\n# reg write wr reg\n%s\n# reg write wr data\n%s\n",
  229. i,
  230. input.stall ? 1 : 0,
  231. input.flush ? 1 : 0,
  232. uint_to_binary_string(input.pc_in, 2),
  233. alu_opcodes[input.exec_op.aluop],
  234. input.exec_op.alusrc1 ? 1 : 0,
  235. input.exec_op.alusrc2 ? 1 : 0,
  236. input.exec_op.alusrc3 ? 1 : 0,
  237. binary_string_n_bits(uint_to_binary_string(output.exec_op.rs1 & 0b11111, 1), 5),
  238. binary_string_n_bits(uint_to_binary_string(output.exec_op.rs2 & 0b11111, 1), 5),
  239. uint_to_binary_string(input.exec_op.readdata1, 4),
  240. uint_to_binary_string(input.exec_op.readdata2, 4),
  241. uint_to_binary_string(input.exec_op.imm, 4),
  242. branchtypes[input.mem_op.branch],
  243. input.mem_op.memread ? 1 : 0,
  244. input.mem_op.memwrite ? 1 : 0,
  245. memtypes[input.mem_op.memtype],
  246. binary_string_n_bits(uint_to_binary_string(input.wb_op.rd & 0b11111, 1), 5),
  247. input.wb_op.write ? 1 : 0,
  248. wbtypes[input.wb_op.src],
  249. input.mem.write ? 1 : 0,
  250. binary_string_n_bits(uint_to_binary_string(input.mem.reg & 0b11111, 1), 5),
  251. uint_to_binary_string(input.mem.data, 4),
  252. input.wr.write ? 1 : 0,
  253. binary_string_n_bits(uint_to_binary_string(input.wr.reg & 0b11111, 1), 5),
  254. uint_to_binary_string(input.wr.data, 4)
  255. );
  256. if (i < (size_t) n - 1)
  257. fprintf(file_input,"\n");
  258. fprintf(
  259. file_output,
  260. "# test case %zu\n# pc old out\n%s\n# pc new out\n%s\n# aluresult\n%s\n# zero\n%c\n# wrdata\n%s\n# aluop\n%s\n# alusrc1\n%d\n# alusrc2\n%d\n# alusrc3\n%d\n# rs1\n%s\n# rs2\n%s\n# readdata1\n%s\n# readdata2\n%s\n# imm\n%s\n# branchtype\n%s\n# memread\n%d\n# memwrite\n%d\n# memtype\n%s\n# wb rd\n%s\n# wb write\n%d\n# wb src\n%s\n",
  261. i,
  262. uint_to_binary_string(output.pc_old_out, 2),
  263. uint_to_binary_string(output.pc_new_out, 2),
  264. uint_to_binary_string(output.aluresult, 4),
  265. output.zero,
  266. uint_to_binary_string(output.wrdata, 4),
  267. alu_opcodes[output.exec_op.aluop],
  268. output.exec_op.alusrc1 ? 1 : 0,
  269. output.exec_op.alusrc2 ? 1 : 0,
  270. output.exec_op.alusrc3 ? 1 : 0,
  271. binary_string_n_bits(uint_to_binary_string(output.exec_op.rs1 & 0b11111, 1), 5),
  272. binary_string_n_bits(uint_to_binary_string(output.exec_op.rs2 & 0b11111, 1), 5),
  273. uint_to_binary_string(output.exec_op.readdata1, 4),
  274. uint_to_binary_string(output.exec_op.readdata2, 4),
  275. uint_to_binary_string(output.exec_op.imm, 4),
  276. branchtypes[output.mem_op.branch],
  277. input.mem_op.memread ? 1 : 0,
  278. input.mem_op.memwrite ? 1 : 0,
  279. memtypes[input.mem_op.memtype],
  280. binary_string_n_bits(uint_to_binary_string(output.wb_op.rd & 0b11111, 1), 5),
  281. output.wb_op.write ? 1 : 0,
  282. wbtypes[output.wb_op.src]
  283. );
  284. if (i < (size_t) n - 1)
  285. fprintf(file_output, "\n");
  286. }
  287. fclose(file_output);
  288. fclose(file_input);
  289. return EXIT_SUCCESS;
  290. }