MipsProcessor.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package tools.mips;
  7. import API.Utils;
  8. import Export.MemoryInitializationFile;
  9. import Export.MultCoreJun;
  10. import common.Instruction;
  11. import java.io.BufferedReader;
  12. import java.io.InputStreamReader;
  13. import java.util.HashMap;
  14. import java.util.Map;
  15. import java.util.TreeMap;
  16. import java.util.logging.Level;
  17. import java.util.logging.Logger;
  18. import targets.mips.Descriprion;
  19. /**
  20. *
  21. * @author EUGENIO CARVALHO
  22. */
  23. public class MipsProcessor {
  24. public String ID = "default";
  25. public Integer WORD = 4, BYTE = 1;
  26. public MipsSettings settings;
  27. public Memory DataMemory;
  28. public Memory InstructionMemory;
  29. public Long PC = 0L;
  30. public RegisterBank RBank;
  31. public HashMap<String, Instruction> instructions = new HashMap<>();
  32. public TreeMap<String, Boolean> breakPoint = new TreeMap<>();
  33. protected HashMap<String, String> Report = new HashMap<>();
  34. public MipsProcessor(MipsSettings settings) throws Exception {
  35. this.settings = new MipsSettings();
  36. this.settings.Set("mode", "debug").Set("step.by.step", "false");
  37. InstructionMemory = new Memory(
  38. settings.Get("memory.instruction"),
  39. settings.GetInt("memory.instruction.size")
  40. );
  41. InstructionMemory.SetIO(new MemoryInitializationFile());
  42. DataMemory = new Memory(
  43. settings.Get("memory.data"),
  44. settings.GetInt("memory.data.size")
  45. );
  46. DataMemory.SetIO(new MemoryInitializationFile());
  47. WORD = 4;
  48. // Limpa todos os dados armazenados
  49. // DataMemory.Reset();
  50. // System.out.println("Init Md:" + DataMemory.R(0L));
  51. RBank = new RegisterBank(32);
  52. InitInstructions();
  53. this.settings.copy(
  54. "debugmode,"
  55. + "mode,"
  56. + "step.by.step,"
  57. + "breakpoints,"
  58. + "memory.instruction,"
  59. + "memory.instruction.size,"
  60. + "memory.data,"
  61. + "memory.data.reset,"
  62. + "memory.data.size",
  63. settings);
  64. SetBreak(this.settings.Get("breakpoints"));
  65. if (this.settings.eq("step.by.step", "true")) {
  66. this.settings.Set("mode", "debug");
  67. }
  68. }
  69. public MipsProcessor SetBreak(String address) {
  70. for (String addrs : address.split(",")) {
  71. if (!addrs.equals("")) {
  72. // Range address
  73. if (addrs.contains("-")) {
  74. String[] parts = addrs.split("-");
  75. Long init = Long.parseLong(parts[0], 16), end = Long.parseLong(parts[1], 16);
  76. for (; init <= end; init += WORD) {
  77. breakPoint.put(Long.toString(init, 16), true);
  78. }
  79. } else {
  80. breakPoint.put(addrs, true);
  81. }
  82. }
  83. }
  84. if (!breakPoint.isEmpty()) {
  85. this.settings.Set("mode", "debug");
  86. System.out.println("Breakpoints:\n" + breakPoint);
  87. }
  88. return this;
  89. }
  90. public MipsProcessor Persist() throws Exception {
  91. DataMemory.Save();
  92. return this;
  93. }
  94. public MipsProcessor Report() throws Exception {
  95. System.out.println(Report);
  96. return this;
  97. }
  98. protected void Log(String msg) {
  99. Log(msg, Long.toHexString(PC));
  100. }
  101. protected void Log(String msg, String pc) {
  102. if (!settings.eq("mode", "debug")) {
  103. return;
  104. }
  105. if (breakPoint.size() > 0 && !breakPoint.containsKey(pc)) {
  106. return;
  107. }
  108. System.out.println(msg);
  109. }
  110. public MipsProcessor Run() throws Exception {
  111. Instruction instruction = null;
  112. Integer interation = 0;
  113. String cAddress = "";
  114. BufferedReader br = null;
  115. Boolean stepByStep = settings.eq("step.by.step", "true");
  116. if (stepByStep || !breakPoint.isEmpty()) {
  117. br = new BufferedReader(new InputStreamReader(System.in));
  118. }
  119. // Carrega o conteudo das memorias
  120. InstructionMemory.ReadFile();
  121. if (!settings.eq("memory.data.reset", "true")) {
  122. DataMemory.ReadFile();
  123. }
  124. // Fetch
  125. // System.out.println("InstructionMemory:" + InstructionMemory);
  126. System.out.println("Start simulation ... " + ID);
  127. try {
  128. while (true) {
  129. instruction = Decode(InstructionMemory.R(PC, WORD));
  130. // Quando encontra a instrucao stop para a simulacao
  131. if (instruction.eq("inst", "stop")) {
  132. break;
  133. }
  134. cAddress = Long.toHexString(PC);
  135. Log("Execute [Interation: " + (interation++)
  136. + "][PC: " + cAddress
  137. + "][Inst: " + instruction.Get("inst")
  138. + "] Next PC:" + Long.toHexString(PC) + "{", cAddress);
  139. // Executa a instrucao
  140. Execute(instruction);
  141. // PC já incrementou
  142. Log("}\nRegistradores(\n" + RBank + ")\n", cAddress);
  143. // Verifica o controle de execução do simulador
  144. if ((stepByStep || breakPoint.containsKey(cAddress)) && br != null) {
  145. br.readLine();
  146. }
  147. }
  148. } catch (Exception e) {
  149. Logger.getLogger(MultCoreJun.class.getName()).log(Level.SEVERE, null, e);
  150. throw new Exception("Simulation error...\n"
  151. + "Execute [Interation: " + (interation++)
  152. + "][PC: " + cAddress
  153. + "][Inst: " + (instruction != null ? instruction.Get("inst") : "")
  154. + "] Next PC:" + Long.toHexString(PC)
  155. + "\nRegistradores(\n" + RBank + ")\n" + e.getMessage()
  156. );
  157. }
  158. Report.put("interations", "" + interation);
  159. return this;
  160. }
  161. public Instruction Decode(String bin) {
  162. // int val = (int) instruction;
  163. // String bin = Utils.Pad(32, Integer.toBinaryString(val));
  164. // System.out.println("Run:" + bin + ":" + bin.length());
  165. String codop = bin.substring(0, 6), key, func = "";
  166. String rs = bin.substring(6, 11),
  167. rt = bin.substring(11, 16);
  168. Long imm;
  169. switch (codop) {
  170. case "000000":
  171. func = bin.substring(26);
  172. key = "@" + func;
  173. break;
  174. case "000001":
  175. key = codop + rt;
  176. break;
  177. // case "000100": //bne bnez
  178. // key = codop + rs;
  179. // break;
  180. default:
  181. key = codop;
  182. }
  183. if (!instructions.containsKey(key)) {
  184. System.out.println("Não encontrou a instrução " + key);
  185. return null;
  186. }
  187. Instruction i = instructions.get(key).copy();
  188. switch (i.Get("type")) {
  189. case "R":
  190. i.Set("rs.bin", rs);
  191. i.Set("rt.bin", rt);
  192. i.Set("rd.bin", bin.substring(16, 21));
  193. i.Set("shamt.bin", bin.substring(21, 26));
  194. i.Set("funct.bin", func);
  195. i.Set("rs", Long.parseLong(rs, 2));
  196. i.Set("rt", Long.parseLong(rt, 2));
  197. i.Set("rd", Long.parseLong(bin.substring(16, 21), 2));
  198. i.Set("shamt", Long.parseLong(bin.substring(21, 26), 2));
  199. i.Set("funct", func);
  200. break;
  201. case "I":
  202. i.Set("rs.bin", rs);
  203. i.Set("rt.bin", rt);
  204. i.Set("imm.bin", bin.substring(16));
  205. i.Set("rs", Long.parseLong(rs, 2));
  206. i.Set("rt", Long.parseLong(rt, 2));
  207. switch (codop) {
  208. case "001101": //ori
  209. case "001100": //andi
  210. bin = bin.substring(16);
  211. break;
  212. default:
  213. bin = Utils.padPreserveSignal(64, bin.substring(16));
  214. }
  215. // System.out.println("I:(" + i.Get("inst") + ")" + Long.parseUnsignedLong(bin, 2));
  216. i.Set("imm", Long.parseUnsignedLong(bin, 2));
  217. break;
  218. case "J":
  219. i.Set("addr.bin", bin.substring(6));
  220. i.Set("imm", Utils.bin32ToDec(bin.substring(6)));
  221. }
  222. return i;
  223. }
  224. protected void InitInstructions() throws Exception {
  225. String key;
  226. for (Map.Entry<String, Instruction> entry : Descriprion.Codops.entrySet()) {
  227. // String string = entry.getKey();
  228. Instruction instruction = entry.getValue();
  229. key = instruction.Get("codop");
  230. switch (key) {
  231. case "000000":
  232. key = "@" + instruction.Get("func");
  233. break;
  234. case "000001":
  235. key += instruction.Get("rt");
  236. break;
  237. // case "000100": //bne bnez
  238. // key += instruction.Get("rs");
  239. // System.out.println("INIT INSTRUCTION:'" + key + "'");
  240. }
  241. instructions.put(key, instruction);
  242. };
  243. }
  244. private void Execute(Instruction inst) throws Exception {
  245. long rs = 0,
  246. rt = 0,
  247. imm = 0,
  248. rd = 0,
  249. shamt = 0;
  250. boolean hasImm = true;
  251. switch (inst.Get("type")) {
  252. case "R":
  253. rd = inst.GetInt("rd");
  254. shamt = inst.GetInt("shamt");
  255. hasImm = false;
  256. case "I":
  257. rs = inst.GetInt("rs");
  258. rt = inst.GetInt("rt");
  259. case "J":
  260. if (hasImm) {
  261. // System.out.println("HAS_IMM:" + inst.Get("imm"));
  262. imm = inst.getLong("imm");
  263. }
  264. }
  265. Log(inst.Get("inst")
  266. + " [rd:" + RBank.names.get((int) rd)
  267. + "] [rs:" + RBank.names.get((int) rs)
  268. + "] [rt:" + RBank.names.get((int) rt)
  269. + "] [shamt:" + shamt
  270. + "] [imm:" + imm + "]");
  271. switch (inst.Get("inst")) {
  272. // R
  273. case "add":
  274. case "addu":
  275. RBank.W(rd, RBank.R(rs) + RBank.R(rt));
  276. break;
  277. case "addi":
  278. case "addiu":
  279. // System.out.println("RBank.R(rs) + imm:" + RBank.R(rs) + ":" + imm);
  280. RBank.W(rt, RBank.R(rs) + imm);
  281. break;
  282. case "stop":
  283. break;
  284. case "and":
  285. case "andi":
  286. RBank.W(rd, RBank.R(rs) & RBank.R(rt));
  287. break;
  288. case "div":
  289. case "divu":
  290. RBank.W(RBank.REG_LO, RBank.R(rs) / RBank.R(rt));
  291. RBank.W(RBank.REG_HI, RBank.R(rs) % RBank.R(rt));
  292. break;
  293. case "jr":
  294. PC = RBank.R(rs);
  295. break;
  296. case "mfhi":
  297. RBank.W(rd, RBank.R(RBank.REG_HI));
  298. break;
  299. case "mflo":
  300. RBank.W(rd, RBank.R(RBank.REG_LO));
  301. break;
  302. case "mthi":
  303. RBank.W(RBank.R(RBank.REG_HI), RBank.R(rs));
  304. break;
  305. case "mtlo":
  306. RBank.W(RBank.R(RBank.REG_LO), RBank.R(rs));
  307. break;
  308. case "mult":
  309. case "multu":
  310. // verificar a questao do hi e lo
  311. // System.out.println("Mult:"
  312. // + rs + "(" + RBank.names.Get((int) rs) + "):"
  313. // + rt + "(" + RBank.names.Get((int) rt) + ")");
  314. RBank.W(RBank.REG_LO, RBank.R(rs) * RBank.R(rt));
  315. break;
  316. // case "nor":
  317. // RBank.W(rd, rs * rt);
  318. // break;
  319. case "or":
  320. RBank.W(rd, RBank.R(rs) | RBank.R(rt));
  321. break;
  322. case "sll":
  323. RBank.W(rd, RBank.R(rt) << shamt);
  324. break;
  325. case "slt":
  326. RBank.W(rd, (RBank.R(rs) < RBank.R(rt)) ? 1 : 0);
  327. break;
  328. case "sra":
  329. RBank.W(rd, RBank.R(rt) >> shamt);
  330. break;
  331. case "srl":
  332. RBank.W(rd, RBank.R(rt) >>> shamt);
  333. break;
  334. case "sub":
  335. case "subu":
  336. RBank.W(rd, RBank.R(rs) - RBank.R(rt));
  337. break;
  338. case "xor":
  339. RBank.W(rd, RBank.R(rs) ^ RBank.R(rt));
  340. break;
  341. // // I
  342. case "beq":
  343. if (RBank.R(rs) == RBank.R(rt)) {
  344. PC += ((imm + 1) << 2);
  345. return;
  346. }
  347. break;
  348. case "bgez":
  349. if (RBank.R(rs) >= 0) {
  350. PC += ((imm + 1) << 2);
  351. return;
  352. }
  353. break;
  354. case "bgtz":
  355. if (RBank.R(rs) > 0) {
  356. PC += ((imm + 1) << 2);
  357. return;
  358. }
  359. break;
  360. case "blez":
  361. if (RBank.R(rs) <= 0) {
  362. PC += ((imm + 1) << 2);
  363. return;
  364. }
  365. break;
  366. case "bltz":
  367. // System.out.println("BLTZ:" + rs);
  368. if (RBank.R(rs) < 0) {
  369. PC += ((imm + 1) << 2);
  370. return;
  371. }
  372. break;
  373. case "bne":
  374. // case "bnez":
  375. // System.out.println("BNE(" + RBank.R(rs) + " / " + RBank.R(rt) + ")" + (RBank.R(rs) != RBank.R(rt)));
  376. if (RBank.R(rs) != RBank.R(rt)) {
  377. PC += ((imm + 1) << 2);
  378. return;
  379. }
  380. break;
  381. // case "lb":
  382. // if (RBank.R(rs) != RBank.R(rt)) {
  383. // PC += imm << 2;
  384. // return;
  385. // }
  386. // case "lbu":
  387. // case "lh":
  388. // case "lhu":
  389. case "lui":
  390. // System.out.println("LUI," + imm + " | " + (imm << 16));
  391. RBank.W(rt, imm << 16);
  392. break;
  393. case "lb":
  394. RBank.W(
  395. rt,
  396. DataMemory.ReadLong(
  397. RBank.R(rs) + imm,
  398. BYTE // Apenas 1 byte
  399. ));
  400. Log(String.format(
  401. "Load address: '%d', value: '%d'\n",
  402. RBank.R(rs) + imm,
  403. DataMemory.ReadLong(RBank.R(rs) + imm, BYTE)
  404. ));
  405. break;
  406. case "lw":
  407. // Escreve no banco de registradores no registrador enderecado por rt
  408. RBank.W(
  409. rt,
  410. // Lê da memoria de dados uma palavra de 4 bytes
  411. DataMemory.ReadLong(
  412. // Endereco de leitura equivale ao conteudo do registrador rs + imediato
  413. RBank.R(rs) + imm,
  414. WORD
  415. ));
  416. Log(String.format(
  417. "Load address: '%d', value: '%d'\n",
  418. RBank.R(rs) + imm,
  419. DataMemory.ReadLong(RBank.R(rs) + imm, WORD)
  420. ));
  421. break;
  422. case "ori":
  423. // System.out.println("ORI:"
  424. // + "\n" + rs
  425. // + "\n" + RBank.R(rs)
  426. // + "\n" + imm
  427. // + "\n" + ((RBank.R(rs) << 16) | imm));
  428. RBank.W(rt, RBank.R(rs) | imm);
  429. break;
  430. case "slti":
  431. // case "sltiu":
  432. case "sw":
  433. DataMemory.W(
  434. RBank.R(rs) + imm,
  435. RBank.R(rt),
  436. WORD // uma palavra inteira
  437. );
  438. if (settings.eq("mode", "debug")) {
  439. DataMemory.Save();
  440. }
  441. Log(String.format("Store '%d' no endereco '%d'\n", RBank.R(rt), RBank.R(rs) + imm));
  442. break;
  443. // case "xori":
  444. // J
  445. case "jal":
  446. RBank.W(31, PC);
  447. case "j":
  448. PC = imm << 2;
  449. return;
  450. default:
  451. throw new Exception("Instrução " + inst.Get("inst") + " não definida!");
  452. }
  453. PC += WORD;
  454. }
  455. }