35 #define RISCV_INVALID_OPCODE 0x0 38 #define PC GetState()->pc 39 #define PC_NEXT GetState()->pc_next 40 #define R GetState()->regs 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]);
50 printf(
"pc: %08x\n\n",
PC);
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,
59 #ifdef ORCA_ENABLE_GDBRSP 75 if (address <=
GetMemory()->GetLastAddr() && address >
77 #ifdef HFRISCV_ENABLE_COUNTERS 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();
84 std::chrono::duration_cast<std::chrono::milliseconds>(duration)
87 _counter_hosttime->Write(millis);
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);
100 GetMemory()->
Read(address, reinterpret_cast<int8_t*>(&data), 4);
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);
113 reinterpret_cast<int8_t*>(&value), 2);
123 std::string err_msg = GetName() +
124 ": could not read from memory, invalid data size requested";
125 throw std::runtime_error(err_msg);
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());
171 if (address <=
GetMemory()->GetLastAddr()) {
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());
181 reinterpret_cast<int8_t*>(&value), size);
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);
192 uint16_t data =
static_cast<uint16_t
>(value);
194 reinterpret_cast<int8_t*>(&data), size);
199 data = (uint8_t)value;
201 reinterpret_cast<int8_t*>(&data), size);
206 std::stringstream ss;
208 <<
": unable to write to unmapped memory space 0x" 209 << std::hex << address <<
".";
210 throw std::runtime_error(ss.str());
222 for (
int i = 0;
i < 4;
i++)
258 output_uart << (int8_t)(value & 0xff) << std::flush;
266 printf(
"%s: exit trap triggered with status 0x%x\n",
267 GetName().c_str(), value);
278 std::stringstream ss;
280 ss << GetName() <<
": unable to write to unmapped memory space 0x" 281 << std::hex << address <<
".";
283 throw std::runtime_error(ss.str());
286 #ifdef HFRISCV_ENABLE_COUNTERS 290 return _counter_iarith;
293 return _counter_ilogical;
296 return _counter_ishift;
299 return _counter_ibranches;
302 return _counter_ijumps;
305 return _counter_iloadstore;
310 return _counter_cycles_total;
313 return _counter_cycles_stall;
316 return _counter_hosttime;
325 void HFRiscV::UpdateCounters(
int opcode,
int funct3) {
331 _counter_ijumps->
Inc(1);
335 _counter_ibranches->Inc(1);
340 _counter_iloadstore->Inc(1);
347 _counter_iarith->Inc(1);
352 _counter_ilogical->Inc(1);
356 _counter_ishift->Inc(1);
361 std::cout <<
"wrn: opcode not accounted for energy estimation" 371 ProcessorBase::Run();
373 #ifdef ORCA_ENABLE_GDBRSP 419 #ifdef HFRISCV_ENABLE_COUNTERS 420 _counter_cycles_stall->Inc(1);
425 #ifdef HFRISCV_ENABLE_COUNTERS 426 _counter_cycles_total->Inc(1);
429 #ifdef HFRISCV_CYCLE_ACCURACY 430 uint32_t pc_next_prediction;
434 uint32_t opcode, rd, rs1, rs2, funct3, funct7,
435 imm_i, imm_s, imm_sb, imm_u, imm_uj;
437 uint32_t *u =
reinterpret_cast<uint32_t *
>(
s->
r);
438 uint32_t ptr_l, ptr_s;
440 #ifdef HFRISCV_CYCLE_ACCURACY 441 uint32_t branch_taken = 0;
449 for (i = 0; i < 4; i++)
458 opcode = inst & 0x7f;
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);
473 if (inst & 0x80000000) {
476 imm_sb |= 0xffffe000;
477 imm_uj |= 0xffe00000;
479 ptr_l = r[rs1] + (int32_t)imm_i;
480 ptr_s = r[rs1] + (int32_t)imm_s;
485 case 0x37: r[rd] = imm_u;
break;
486 case 0x17: r[rd] =
PC + imm_u;
break;
490 PC_NEXT = (r[rs1] + imm_i) & 0xfffffffe;
495 #ifdef HFRISCV_CYCLE_ACCURACY 501 if (r[rs1] == r[rs2]) {
PC_NEXT =
PC + imm_sb; }
504 if (r[rs1] != r[rs2]) {
PC_NEXT =
PC + imm_sb; }
507 if (r[rs1] < r[rs2]) {
PC_NEXT =
PC + imm_sb; }
510 if (r[rs1] >= r[rs2]) {
PC_NEXT =
PC + imm_sb; }
513 if (u[rs1] < u[rs2]) {
PC_NEXT =
PC + imm_sb; }
516 if (u[rs1] >= u[rs2]) {
PC_NEXT =
PC + imm_sb; }
522 #ifdef HFRISCV_CYCLE_ACCURACY 523 branch_taken = (pc_next_prediction !=
PC_NEXT);
531 r[rd] =
static_cast<int8_t
>(
mem_read(
s, 1, ptr_l));
534 r[rd] =
static_cast<int16_t
>(
mem_read(
s, 2, ptr_l));
540 r[rd] =
static_cast<uint8_t
>(
mem_read(
s, 1, ptr_l));
543 r[rd] =
static_cast<uint16_t
>(
mem_read(
s, 2, ptr_l));
565 r[rd] = r[rs1] +
static_cast<int32_t
>(imm_i);
568 r[rd] = r[rs1] <
static_cast<int32_t
>(imm_i);
571 r[rd] = u[rs1] <
static_cast<uint32_t
>(imm_i);
574 r[rd] = r[rs1] ^
static_cast<int32_t
>(imm_i);
577 r[rd] = r[rs1] |
static_cast<int32_t
>(imm_i);
580 r[rd] = r[rs1] &
static_cast<int32_t
>(imm_i);
583 r[rd] = u[rs1] << (rs2 & 0x3f);
588 r[rd] = u[rs1] >> (rs2 & 0x3f);
591 r[rd] = r[rs1] >> (rs2 & 0x3f);
603 r[rd] = (((int64_t)r[rs1] * (int64_t)r[rs2])
607 r[rd] = ((((int64_t)r[rs1] * (int64_t)r[rs2]) >> 32)
611 r[rd] = ((((int64_t)r[rs1] * (uint64_t)u[rs2]) >> 32)
615 r[rd] = ((((uint64_t)u[rs1] * (uint64_t)u[rs2]) >> 32)
620 r[rd] = r[rs1] / r[rs2];
626 r[rd] = u[rs1] / u[rs2];
632 r[rd] = r[rs1] % r[rs2];
638 r[rd] = u[rs1] % u[rs2];
650 r[rd] = r[rs1] + r[rs2];
653 r[rd] = r[rs1] - r[rs2];
659 r[rd] = r[rs1] << r[rs2];
662 r[rd] = r[rs1] < r[rs2];
665 r[rd] = u[rs1] < u[rs2];
668 r[rd] = r[rs1] ^ r[rs2];
673 r[rd] = u[rs1] >> u[rs2];
676 r[rd] = r[rs1] >> r[rs2];
681 case 0x6: r[rd] = r[rs1] | r[rs2];
break;
682 case 0x7: r[rd] = r[rs1] & r[rs2];
break;
690 std::stringstream ss;
691 ss << GetName() <<
":invalid opcode (at pc=0x" << std::hex <<
PC;
692 ss <<
" opcode=0x" << std::hex << inst <<
")";
697 throw std::runtime_error(ss.str());
706 for (i = 0; i < 3; i++)
709 #ifdef HFRISCV_ENABLE_COUNTERS
710 UpdateCounters(opcode, funct3);
713 #ifdef HFRISCV_CYCLE_ACCURACY 721 return (branch_taken) ? 1 : 2;
753 for (
i = 0;
i < 4;
i++)
767 +
"_debug.log", std::ofstream::out | std::ofstream::trunc);
769 +
"_uart.log", std::ofstream::out | std::ofstream::trunc);
771 #ifdef HFRISCV_ENABLE_COUNTERS 778 _counter_iloadstore =
780 _counter_cycles_total =
782 _counter_cycles_stall =
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;
798 delete _counter_cycles_total;
799 delete _counter_cycles_stall;
801 delete _counter_hosttime;
std::ofstream output_debug
std::ofstream output_uart
The Signal class models a generic bus of width equals to the sizeof(T)
void Write(uint32_t addr, MemoryType *data, uint32_t length)
Writes data to the memory.
#define HFRISCV_PC_MEMBASE
void bp(risc_v_state *s, uint32_t ir)
HFRiscV(std::string name, Signal< uint8_t > *intr, Signal< uint8_t > *stall, Memory *mem)
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.
Signal< uint8_t > * GetSignalStall()
void mem_write(risc_v_state *s, int32_t size, uint32_t address, uint32_t value)
Reads data from memory.
ProcessorState< uint32_t > * GetState()
This method returns the state model of the processor.
void Read(uint32_t addr, MemoryType *buffer, uint32_t length)
Reads data from a given memory location.
Signal< uint8_t > * _signal_stall
#define RISCV_INVALID_OPCODE
int32_t mem_read(risc_v_state *s, int32_t size, uint32_t address)
Reads data from the memory.
This class models a memory module.
This class implements the base operation for generic processor implementations.
Signal< uint8_t > * GetSignalIntr()
void Inc(T val)
Increments the value of the bus by the given value.
SimulationTime Run()
Run method from the base TimedModel class, overloaded.
Signal< uint8_t > * _signal_intr