orca-sim
HFRiscV.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * This file is part of project ORCA. More information on the project
3  * can be found at the following repositories at GitHub's website.
4  *
5  * http://https://github.com/andersondomingues/orca-sim
6  * http://https://github.com/andersondomingues/orca-software
7  * http://https://github.com/andersondomingues/orca-mpsoc
8  * http://https://github.com/andersondomingues/orca-tools
9  *
10  * Copyright (C) 2018-2020 Anderson Domingues, <ti.andersondomingues@gmail.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 ******************************************************************************/
26 #include <cstdlib>
27 #include <sstream>
28 #include <chrono>
29 
30 #include "sys/time.h"
31 
32 #include "HFRiscV.hpp"
33 #include "Signal.hpp"
34 
35 #define RISCV_INVALID_OPCODE 0x0
36 
37 // api access shorthands (must be undef at the end of the file)
38 #define PC GetState()->pc
39 #define PC_NEXT GetState()->pc_next
40 #define R GetState()->regs
41 
43 
44 void HFRiscV::dumpregs() {
45  for (uint32_t i = 0; i < 32; i += 4) {
46  printf("r%02d [%08x] r%02d [%08x] r%02d [%08x] r%02d [%08x]\n", \
47  i, R[i], i+1, R[i+1], i+2, R[i+2], i+3, R[i+3]);
48  }
49 
50  printf("pc: %08x\n\n", PC);
51 }
52 
53 void HFRiscV::bp(risc_v_state *s, uint32_t ir) {
54  printf("Breakpoint reached at 0x%x (ir: %08x)", PC, ir);
55  printf("irq_status: %08x, irq_cause: %08x, irq_mask: %08x\n", s->status,
56  s->cause, s->mask);
57  dumpregs();
58 
59  #ifdef ORCA_ENABLE_GDBRSP
60  GetState()->bp = 0x1;
61  #endif
62 }
63 
71 int32_t HFRiscV::mem_read(risc_v_state *s, int32_t size, uint32_t address) {
72  uint32_t data;
73 
74  // Check whether the address belongs to the main memory
75  if (address <= GetMemory()->GetLastAddr() && address >
76  GetMemory()->GetBase()) {
77  #ifdef HFRISCV_ENABLE_COUNTERS
78  // get information on host's clock (real clock, in hours, not cycles)
79  if (address == _counter_hosttime->GetAddress()) {
80  std::chrono::time_point<std::chrono::system_clock> now
81  = std::chrono::system_clock::now();
82  auto duration = now.time_since_epoch();
83  auto millis =
84  std::chrono::duration_cast<std::chrono::milliseconds>(duration)
85  .count();
86 
87  _counter_hosttime->Write(millis);
88  }
89  #endif
90 
91  switch (size) {
92  case 4:
93  if (address & 3) {
94  std::string err_msg = GetName() +
95  ": unaligned access (load word) pc=0x" +
96  std::to_string(PC) + " addr=0x" + std::to_string(address);
97  throw std::runtime_error(err_msg);
98  } else {
99  // 4 x sizeof(uint8_t)
100  GetMemory()->Read(address, reinterpret_cast<int8_t*>(&data), 4);
101  }
102  break;
103  case 2:
104  if (address & 1) {
105  std::string err_msg = GetName()
106  + ": unaligned access (load halfword) pc=0x"
107  + std::to_string(PC) + " addr=0x" + std::to_string(address);
108  throw std::runtime_error(err_msg);
109  } else {
110  int16_t value;
111  // 2 x sizeof(uint8_t)
112  GetMemory()->Read(address,
113  reinterpret_cast<int8_t*>(&value), 2);
114  data = value;
115  }
116  break;
117  case 1:
118  int8_t value;
119  GetMemory()->Read(address, &value, 1); // 1 x sizeof(uint8_t)
120  data = value;
121  break;
122  default:
123  std::string err_msg = GetName() +
124  ": could not read from memory, invalid data size requested";
125  throw std::runtime_error(err_msg);
126  }
127 
128  return data;
129  } else {
130  // Address does not belong to any bank, check for special addresses
131  switch (address) {
132  case IRQ_VECTOR: return s->vector;
133  case IRQ_CAUSE: return s->cause | 0x0080 | 0x0040;
134  case IRQ_MASK: return s->mask;
135  case IRQ_STATUS: return s->status;
136  case IRQ_EPC: return s->epc;
137  case COUNTER: return s->counter;
138  case COMPARE: return s->compare;
139  case COMPARE2: return s->compare2;
140  case UART_READ: return getchar();
141  case UART_DIVISOR: return 0;
142  }
143 
144  // may the requested address fall in unmapped range, halt the simulation
145  dumpregs();
146  std::stringstream ss;
147  ss << GetName() << ": unable to read from unmapped memory space 0x"
148  << std::hex << address << ".";
149  throw std::runtime_error(ss.str());
150  }
151 }
152 
154  return _signal_stall;
155 }
156 
158  return _signal_intr;
159 }
160 
168 void HFRiscV::mem_write(risc_v_state *s, int32_t size, uint32_t address,
169  uint32_t value) {
170  // if the address belong to some memory range, write to it
171  if (address <= GetMemory()->GetLastAddr()) {
172  switch (size) {
173  case 4:
174  if (address & 3) {
175  std::stringstream ss;
176  ss << GetName() << ": unaligned access (store word) pc=0x"
177  << std::hex << PC << " addr=0x" << std::hex << address;
178  throw std::runtime_error(ss.str());
179  } else {
180  GetMemory()->Write(address,
181  reinterpret_cast<int8_t*>(&value), size);
182  }
183  break;
184  case 2:
185  if (address & 1) {
186  std::string err_msg = GetName()
187  + ": unaligned access (store halfword) pc=0x"
188  + std::to_string(PC) + " addr=0x"
189  + std::to_string(address);
190  throw std::runtime_error(err_msg);
191  } else {
192  uint16_t data = static_cast<uint16_t>(value);
193  GetMemory()->Write(address,
194  reinterpret_cast<int8_t*>(&data), size);
195  }
196  break;
197  case 1: {
198  uint8_t data;
199  data = (uint8_t)value;
200  GetMemory()->Write(address,
201  reinterpret_cast<int8_t*>(&data), size);
202  break;
203  }
204  default: {
205  dumpregs();
206  std::stringstream ss;
207  ss << GetName()
208  << ": unable to write to unmapped memory space 0x"
209  << std::hex << address << ".";
210  throw std::runtime_error(ss.str());
211  }
212  }
213  return; // succefully written
214  }
215 
216  // may the request memory space be out of the mapped memory range, we assume
217  // the code is pointing to some of the special addresses
218  switch (address) {
219  case IRQ_STATUS: {
220  if (value == 0) {
221  s->status = 0;
222  for (int i = 0; i < 4; i++)
223  s->status_dly[i] = 0;
224  } else {
225  s->status_dly[3] = value;
226  }
227  return;
228  }
229 
230  case IRQ_VECTOR:
231  s->vector = value;
232  return;
233  case IRQ_CAUSE:
234  s->cause = value;
235  return;
236  case IRQ_MASK:
237  s->mask = value;
238  return;
239  case IRQ_EPC:
240  s->epc = value;
241  return;
242  case COUNTER:
243  s->counter = value;
244  return;
245  case COMPARE:
246  s->compare = value;
247  s->cause &= 0xffef;
248  return;
249  case COMPARE2:
250  s->compare2 = value;
251  s->cause &= 0xffdf;
252  return;
253 
254  case DEBUG_ADDR:
255  output_debug << (int8_t)(value & 0xff) << std::flush;
256  return;
257  case UART_WRITE:
258  output_uart << (int8_t)(value & 0xff) << std::flush;
259  return;
260  case UART_DIVISOR: return;
261 
262  case EXIT_TRAP:
263 
264  // write cause of aborting to special register
265  GetState()->terminated = value;
266  printf("%s: exit trap triggered with status 0x%x\n",
267  GetName().c_str(), value);
268 
269  output_debug.close();
270  output_uart.close();
271 
272  return;
273  }
274 
275  // if none of the special address has been reach, the requested
276  // address if unknown to the system and we should halt the simulation
277  dumpregs();
278  std::stringstream ss;
279 
280  ss << GetName() << ": unable to write to unmapped memory space 0x"
281  << std::hex << address << ".";
282 
283  throw std::runtime_error(ss.str());
284 }
285 
286 #ifdef HFRISCV_ENABLE_COUNTERS
287 
288 // Counters' getters
289 Signal<uint32_t>* HFRiscV::GetSignalCounterArith() {
290  return _counter_iarith;
291 }
292 Signal<uint32_t>* HFRiscV::GetSignalCounterLogical() {
293  return _counter_ilogical;
294 }
295 Signal<uint32_t>* HFRiscV::GetSignalCounterShift() {
296  return _counter_ishift;
297 }
298 Signal<uint32_t>* HFRiscV::GetSignalCounterBranches() {
299  return _counter_ibranches;
300 }
301 Signal<uint32_t>* HFRiscV::GetSignalCounterJumps() {
302  return _counter_ijumps;
303 }
304 Signal<uint32_t>* HFRiscV::GetSignalCounterLoadStore() {
305  return _counter_iloadstore;
306 }
307 
308 // cycles
309 Signal<uint32_t>* HFRiscV::GetSignalCounterCyclesTotal() {
310  return _counter_cycles_total;
311 }
312 Signal<uint32_t>* HFRiscV::GetSignalCounterCyclesStall() {
313  return _counter_cycles_stall;
314 }
315 Signal<uint32_t>* HFRiscV::GetSignalHostTime() {
316  return _counter_hosttime;
317 }
318 
325 void HFRiscV::UpdateCounters(int opcode, int funct3) {
326  switch (opcode) {
327  case 0x37: // LUI
328  case 0x17: // ALUI
329  case 0x6f: // JAL
330  case 0x67: // JALR
331  _counter_ijumps->Inc(1);
332  break;
333 
334  case 0x63: // branches
335  _counter_ibranches->Inc(1);
336  break;
337 
338  case 0x3: // loads
339  case 0x23: // stores
340  _counter_iloadstore->Inc(1);
341  break;
342 
343  case 0x13: // type R
344  case 0x33:
345  switch (funct3) {
346  case 0x0: // addi, subi
347  _counter_iarith->Inc(1);
348  break;
349  case 0x4: // xori
350  case 0x6: // ori
351  case 0x7: // andi
352  _counter_ilogical->Inc(1);
353  break;
354 
355  default: // shifts i
356  _counter_ishift->Inc(1);
357  break;
358  }
359  break;
360  default:
361  std::cout << "wrn: opcode not accounted for energy estimation"
362  << std::endl;
363  break;
364  }
365 }
366 #endif /* HFRISCV_ENABLE_COUNTERS */
367 
369  // call ancestor method which handles
370  // generic tasks all processor models
371  ProcessorBase::Run();
372 
373  #ifdef ORCA_ENABLE_GDBRSP
374  // When operating with GDB support, the pause flags indicates
375  // the processor core must skip the current cycle without mo-
376  // fiying any of their registers. This flags acts as a second
377  // stall line. Since this line is used only by the gbdrsp imp-
378  // lementation, we do not set this flag as a wire, as it does
379  // not exist in the real design (yet).
380  if (GetState()->pause == 0x1)
381  return 1;
382  #endif
383 
384  // update "external counters"
385  s->counter++;
386 
387  /*IRQ_COMPARE2*/
388  if ((s->compare2 & 0xffffff) == (s->counter & 0xffffff)) s->cause |= 0x20;
389  /*IRQ_COMPARE*/
390  if (s->compare == s->counter) s->cause |= 0x10;
391  /*IRQ_COUNTER2_NOT*/
392  if (!(s->counter & 0x10000))
393  s->cause |= 0x8;
394  else
395  s->cause &= 0xfffffff7;
396  /*IRQ_COUNTER2*/
397  if (s->counter & 0x10000)
398  s->cause |= 0x4;
399  else
400  s->cause &= 0xfffffffb;
401  /*IRQ_COUNTER_NOT*/
402  if (!(s->counter & 0x40000))
403  s->cause |= 0x2;
404  else
405  s->cause &= 0xfffffffd;
406  /*IRQ_COUNTER*/
407  if (s->counter & 0x40000)
408  s->cause |= 0x1;
409  else
410  s->cause &= 0xfffffffe;
411  /*IRQ_NOC*/
412  if (_signal_intr->Read() == 0x1)
413  s->cause |= 0x100;
414  else
415  s->cause &= 0xfffffeff;
416 
417  // skip current cycle if stall is risen
418  if (_signal_stall->Read() == 0x1) {
419  #ifdef HFRISCV_ENABLE_COUNTERS
420  _counter_cycles_stall->Inc(1);
421  #endif
422  return 1;
423  }
424 
425  #ifdef HFRISCV_ENABLE_COUNTERS
426  _counter_cycles_total->Inc(1);
427  #endif
428 
429  #ifdef HFRISCV_CYCLE_ACCURACY
430  uint32_t pc_next_prediction;
431  #endif
432 
433  uint32_t inst, i;
434  uint32_t opcode, rd, rs1, rs2, funct3, funct7,
435  imm_i, imm_s, imm_sb, imm_u, imm_uj;
436  int32_t *r = s->r;
437  uint32_t *u = reinterpret_cast<uint32_t *>(s->r);
438  uint32_t ptr_l, ptr_s;
439 
440  #ifdef HFRISCV_CYCLE_ACCURACY
441  uint32_t branch_taken = 0;
442  #endif
443 
444  if (s->status && (s->cause & s->mask)) {
445  s->epc = PC_NEXT;
446  PC = s->vector;
447  PC_NEXT = s->vector + 4;
448  s->status = 0;
449  for (i = 0; i < 4; i++)
450  s->status_dly[i] = 0;
451  }
452 
453  // FETCH STAGE
454  // 4 x sizeof(uint8_t)
455  GetMemory()->Read(PC, reinterpret_cast<int8_t*>(&inst), 4);
456 
457  // DECODE
458  opcode = inst & 0x7f;
459 
460  rd = (inst >> 7) & 0x1f;
461  rs1 = (inst >> 15) & 0x1f;
462  rs2 = (inst >> 20) & 0x1f;
463  funct3 = (inst >> 12) & 0x7;
464  funct7 = (inst >> 25) & 0x7f;
465  imm_i = (inst & 0xfff00000) >> 20;
466  imm_s = ((inst & 0xf80) >> 7) | ((inst & 0xfe000000) >> 20);
467  imm_sb = ((inst & 0xf00) >> 7) | ((inst & 0x7e000000) >> 20)
468  | ((inst & 0x80) << 4) | ((inst & 0x80000000) >> 19);
469  imm_u = inst & 0xfffff000;
470  imm_uj = ((inst & 0x7fe00000) >> 20) | ((inst & 0x100000) >> 9)
471  | (inst & 0xff000) | ((inst & 0x80000000) >> 11);
472 
473  if (inst & 0x80000000) {
474  imm_i |= 0xfffff000;
475  imm_s |= 0xfffff000;
476  imm_sb |= 0xffffe000;
477  imm_uj |= 0xffe00000;
478  }
479  ptr_l = r[rs1] + (int32_t)imm_i;
480  ptr_s = r[rs1] + (int32_t)imm_s;
481  r[0] = 0;
482 
483  // EXECUTE
484  switch (opcode) {
485  case 0x37: r[rd] = imm_u; break; // LUI
486  case 0x17: r[rd] = PC + imm_u; break; // AUIPC
487  case 0x6f: r[rd] = PC_NEXT; PC_NEXT = PC + imm_uj; break; // JAL
488  case 0x67: // JALR
489  r[rd] = PC_NEXT;
490  PC_NEXT = (r[rs1] + imm_i) & 0xfffffffe;
491  break;
492  case 0x63:
493  /* Branch prediction may fail if jumping 0 positions.
494  TODO: check whether the architecture predict such jumps */
495  #ifdef HFRISCV_CYCLE_ACCURACY
496  pc_next_prediction = PC_NEXT;
497  #endif
498 
499  switch (funct3) {
500  case 0x0: // BEQ
501  if (r[rs1] == r[rs2]) { PC_NEXT = PC + imm_sb; }
502  break;
503  case 0x1: // BNE
504  if (r[rs1] != r[rs2]) { PC_NEXT = PC + imm_sb; }
505  break;
506  case 0x4: // BLT
507  if (r[rs1] < r[rs2]) { PC_NEXT = PC + imm_sb; }
508  break;
509  case 0x5: // BGE
510  if (r[rs1] >= r[rs2]) { PC_NEXT = PC + imm_sb; }
511  break;
512  case 0x6: // BLTU
513  if (u[rs1] < u[rs2]) { PC_NEXT = PC + imm_sb; }
514  break;
515  case 0x7: // BGEU
516  if (u[rs1] >= u[rs2]) { PC_NEXT = PC + imm_sb; }
517  break;
518  default:
519  goto fail;
520  }
521 
522  #ifdef HFRISCV_CYCLE_ACCURACY
523  branch_taken = (pc_next_prediction != PC_NEXT);
524  #endif
525 
526  break;
527 
528  case 0x3:
529  switch (funct3) {
530  case 0x0: // LB
531  r[rd] = static_cast<int8_t>(mem_read(s, 1, ptr_l));
532  break;
533  case 0x1: // LH
534  r[rd] = static_cast<int16_t>(mem_read(s, 2, ptr_l));
535  break;
536  case 0x2: // LW
537  r[rd] = mem_read(s, 4, ptr_l);
538  break;
539  case 0x4: // LBU
540  r[rd] = static_cast<uint8_t>(mem_read(s, 1, ptr_l));
541  break;
542  case 0x5: // LHU
543  r[rd] = static_cast<uint16_t>(mem_read(s, 2, ptr_l));
544  break;
545  default: goto fail;
546  }
547  break;
548  case 0x23:
549  switch (funct3) {
550  case 0x0: // SB
551  mem_write(s, 1, ptr_s, r[rs2]);
552  break;
553  case 0x1: // SH
554  mem_write(s, 2, ptr_s, r[rs2]);
555  break;
556  case 0x2: // SW
557  mem_write(s, 4, ptr_s, r[rs2]);
558  break;
559  default: goto fail;
560  }
561  break;
562  case 0x13:
563  switch (funct3) {
564  case 0x0: // ADDI
565  r[rd] = r[rs1] + static_cast<int32_t>(imm_i);
566  break;
567  case 0x2: // SLTI
568  r[rd] = r[rs1] < static_cast<int32_t>(imm_i);
569  break;
570  case 0x3: // SLTIU
571  r[rd] = u[rs1] < static_cast<uint32_t>(imm_i);
572  break;
573  case 0x4: // XORI
574  r[rd] = r[rs1] ^ static_cast<int32_t>(imm_i);
575  break;
576  case 0x6: // ORI
577  r[rd] = r[rs1] | static_cast<int32_t>(imm_i);
578  break;
579  case 0x7: // ANDI
580  r[rd] = r[rs1] & static_cast<int32_t>(imm_i);
581  break;
582  case 0x1: // SLLI
583  r[rd] = u[rs1] << (rs2 & 0x3f);
584  break;
585  case 0x5:
586  switch (funct7) {
587  case 0x0: // SRLI
588  r[rd] = u[rs1] >> (rs2 & 0x3f);
589  break;
590  case 0x20: // SRAI
591  r[rd] = r[rs1] >> (rs2 & 0x3f);
592  break;
593  default: goto fail;
594  }
595  break;
596  default: goto fail;
597  }
598  break;
599  case 0x33:
600  if (funct7 == 0x1) { // RV32M
601  switch (funct3) {
602  case 0: // MUL
603  r[rd] = (((int64_t)r[rs1] * (int64_t)r[rs2])
604  & 0xffffffff);
605  break;
606  case 1: // MULH
607  r[rd] = ((((int64_t)r[rs1] * (int64_t)r[rs2]) >> 32)
608  & 0xffffffff);
609  break;
610  case 2: // MULHSU
611  r[rd] = ((((int64_t)r[rs1] * (uint64_t)u[rs2]) >> 32)
612  & 0xffffffff);
613  break;
614  case 3: // ULHU
615  r[rd] = ((((uint64_t)u[rs1] * (uint64_t)u[rs2]) >> 32)
616  & 0xffffffff);
617  break;
618  case 4: // DIV
619  if (r[rs2])
620  r[rd] = r[rs1] / r[rs2];
621  else
622  r[rd] = 0;
623  break;
624  case 5: // DIVU
625  if (r[rs2])
626  r[rd] = u[rs1] / u[rs2];
627  else
628  r[rd] = 0;
629  break;
630  case 6: // REM
631  if (r[rs2])
632  r[rd] = r[rs1] % r[rs2];
633  else
634  r[rd] = 0;
635  break;
636  case 7: // REMU
637  if (r[rs2])
638  r[rd] = u[rs1] % u[rs2];
639  else
640  r[rd] = 0;
641  break;
642  default: goto fail;
643  }
644  break;
645  } else {
646  switch (funct3) {
647  case 0x0:
648  switch (funct7) {
649  case 0x0: // ADD
650  r[rd] = r[rs1] + r[rs2];
651  break;
652  case 0x20: // SUB
653  r[rd] = r[rs1] - r[rs2];
654  break;
655  default: goto fail;
656  }
657  break;
658  case 0x1: // SLL
659  r[rd] = r[rs1] << r[rs2];
660  break;
661  case 0x2: // SLT
662  r[rd] = r[rs1] < r[rs2];
663  break;
664  case 0x3: // SLTU
665  r[rd] = u[rs1] < u[rs2];
666  break;
667  case 0x4: // XOR
668  r[rd] = r[rs1] ^ r[rs2];
669  break;
670  case 0x5:
671  switch (funct7) {
672  case 0x0: // SRL
673  r[rd] = u[rs1] >> u[rs2];
674  break;
675  case 0x20: // SRA
676  r[rd] = r[rs1] >> r[rs2];
677  break;
678  default: goto fail;
679  }
680  break;
681  case 0x6: r[rd] = r[rs1] | r[rs2]; break; // OR
682  case 0x7: r[rd] = r[rs1] & r[rs2]; break; // AND
683  default: goto fail;
684  }
685  break;
686  }
687  break;
688  default:
689 fail:
690  std::stringstream ss;
691  ss << GetName() << ":invalid opcode (at pc=0x" << std::hex << PC;
692  ss << " opcode=0x" << std::hex << inst << ")";
693 
694  dumpregs();
696 
697  throw std::runtime_error(ss.str());
698  break;
699  }
700 
701  _last_pc = PC;
702  PC = PC_NEXT;
703  PC_NEXT = PC_NEXT + 4;
704  s->status = s->status_dly[0];
705 
706  for (i = 0; i < 3; i++)
707  s->status_dly[i] = s->status_dly[i+1];
708 
709  #ifdef HFRISCV_ENABLE_COUNTERS
710  UpdateCounters(opcode, funct3);
711  #endif
712 
713  #ifdef HFRISCV_CYCLE_ACCURACY
714  // When in cycle-accuracy mode, takes three cycles per instruction,
715  // except for those of memory I/O. In the later case. Since we simulate
716  // the pipeline by executing one instruction per cycle (starting from
717  // the 3th cycle), adding 1 cycle to simulate I/O delay. We also calculate
718  // branch prediction.
719  switch (opcode) {
720  case 0x63:
721  return (branch_taken) ? 1 : 2;
722  break;
723  case 0x23:
724  case 0x3:
725  return 2;
726  break;
727  default:
728  return 1;
729  break;
730  }
731  #else
732  // When in instruction mode, evey instruction takes exactly one cycle to
733  // leave the pipeline. This mode aims for performance.
734  return 1;
735  #endif
736 }
737 
738 HFRiscV::HFRiscV(std::string name, Signal<uint8_t>* intr,
739  Signal<uint8_t>* stall, Memory* mainmem)
740  : ProcessorBase(name, HFRISCV_PC_MEMBASE, mainmem) {
741 
742  s = new risc_v_state;
743  memset(s, 0, sizeof(risc_v_state));
744 
746  PC_NEXT = PC + 4;
747 
748  s->vector = 0;
749  s->cause = 0;
750  s->mask = 0;
751  s->status = 0;
752 
753  for (i = 0; i < 4; i++)
754  s->status_dly[i] = 0;
755 
756  s->epc = 0;
757  s->counter = 0;
758  s->compare = 0;
759  s->compare2 = 0;
760  // s->cycles = 0;
761 
762  // set interruption wire (to be managed by the top-level module)
763  _signal_intr = intr;
764  _signal_stall = stall;
765 
766  output_debug.open("logs/" + GetName()
767  + "_debug.log", std::ofstream::out | std::ofstream::trunc);
768  output_uart.open("logs/" + GetName()
769  + "_uart.log", std::ofstream::out | std::ofstream::trunc);
770 
771  #ifdef HFRISCV_ENABLE_COUNTERS
772  _counter_iarith = new Signal<uint32_t>(GetName() + ".counters.iarith");
773  _counter_ilogical = new Signal<uint32_t>(GetName() + ".counters.ilogical");
774  _counter_ishift = new Signal<uint32_t>(GetName() + ".counters.ishift");
775  _counter_ibranches =
776  new Signal<uint32_t>(GetName() + ".counters.ibranches");
777  _counter_ijumps = new Signal<uint32_t>(GetName() + ".counters.ijumps");
778  _counter_iloadstore =
779  new Signal<uint32_t>(GetName() + ".counters.iloadstore");
780  _counter_cycles_total =
781  new Signal<uint32_t>(GetName() + ".counters.cycles_total");
782  _counter_cycles_stall =
783  new Signal<uint32_t>(GetName() + ".counters.cycles_stall");
784 
785  _counter_hosttime = new Signal<uint32_t>(GetName() + ".counters.hosttime");
786  #endif
787 }
788 
790  #ifdef HFRISCV_ENABLE_COUNTERS
791  delete _counter_iarith;
792  delete _counter_ilogical;
793  delete _counter_ishift;
794  delete _counter_ibranches;
795  delete _counter_ijumps;
796  delete _counter_iloadstore;
797 
798  delete _counter_cycles_total;
799  delete _counter_cycles_stall;
800 
801  delete _counter_hosttime;
802 
803  #endif
804 }
805 
807  // TODO(ad): to be implemented
808  return;
809 }
810 
811 // api access shorthands (must be undef at the end of the file)
812 #undef PC
813 #undef PC_NEXT
814 #undef R
The Signal class models a generic bus of width equals to the sizeof(T)
Definition: Signal.hpp:45
#define IRQ_STATUS
Definition: HFRiscV.hpp:50
void Write(uint32_t addr, MemoryType *data, uint32_t length)
Writes data to the memory.
Definition: Memory.cpp:75
#define HFRISCV_PC_MEMBASE
Definition: HFRiscV.hpp:44
void bp(risc_v_state *s, uint32_t ir)
Definition: HFRiscV.cpp:53
#define R
Definition: HFRiscV.cpp:40
#define UART_DIVISOR
Definition: HFRiscV.hpp:60
#define DEBUG_ADDR
Definition: HFRiscV.hpp:57
#define PC_NEXT
Definition: HFRiscV.cpp:39
HFRiscV(std::string name, Signal< uint8_t > *intr, Signal< uint8_t > *stall, Memory *mem)
Definition: HFRiscV.cpp:738
#define COMPARE2
Definition: HFRiscV.hpp:54
#define COMPARE
Definition: HFRiscV.hpp:53
#define UART_READ
Definition: HFRiscV.hpp:59
Memory * GetMemory()
This method returns a pointer to the object that models the memory core.
T Read()
Get the last value writen to the bus.
Definition: Signal.cpp:118
Signal< uint8_t > * GetSignalStall()
Definition: HFRiscV.cpp:153
void mem_write(risc_v_state *s, int32_t size, uint32_t address, uint32_t value)
Reads data from memory.
Definition: HFRiscV.cpp:168
uint32_t SimulationTime
ProcessorState< uint32_t > * GetState()
This method returns the state model of the processor.
#define IRQ_CAUSE
Definition: HFRiscV.hpp:48
#define UART_WRITE
Definition: HFRiscV.hpp:58
void Read(uint32_t addr, MemoryType *buffer, uint32_t length)
Reads data from a given memory location.
Definition: Memory.cpp:111
#define IRQ_EPC
Definition: HFRiscV.hpp:51
#define PC
Definition: HFRiscV.cpp:38
Signal< uint8_t > * _signal_stall
Definition: HFRiscV.hpp:82
#define EXIT_TRAP
Definition: HFRiscV.hpp:46
#define RISCV_INVALID_OPCODE
Definition: HFRiscV.cpp:35
#define IRQ_MASK
Definition: HFRiscV.hpp:49
int32_t mem_read(risc_v_state *s, int32_t size, uint32_t address)
Reads data from the memory.
Definition: HFRiscV.cpp:71
This class models a memory module.
Definition: Memory.hpp:55
This class implements the base operation for generic processor implementations.
Signal< uint8_t > * GetSignalIntr()
Definition: HFRiscV.cpp:157
#define IRQ_VECTOR
Definition: HFRiscV.hpp:47
void Inc(T val)
Increments the value of the bus by the given value.
Definition: Signal.cpp:136
SimulationTime Run()
Run method from the base TimedModel class, overloaded.
Definition: HFRiscV.cpp:368
Signal< uint8_t > * _signal_intr
Definition: HFRiscV.hpp:81
#define COUNTER
Definition: HFRiscV.hpp:52