Entering debug mode now jumps to "dynamic rom"
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "opcodes.h"
6 #include "mmu.h"
7
8 #include "debug_rom/debug_rom.h"
9
10 #if 1
11 # define D(x) x
12 #else
13 # define D(x)
14 #endif
15
16 debug_module_t::debug_module_t(sim_t *sim) : sim(sim)
17 {
18 dmcontrol.version = 1;
19
20 write32(debug_rom_entry, 0, jal(0, 0));
21 }
22
23 void debug_module_t::reset()
24 {
25 for (unsigned i = 0; i < sim->nprocs(); i++) {
26 processor_t *proc = sim->get_core(i);
27 if (proc)
28 proc->halt_request = false;
29 }
30
31 dmcontrol.haltreq = 0;
32 dmcontrol.reset = 0;
33 dmcontrol.dmactive = 0;
34 dmcontrol.hartsel = 0;
35 dmcontrol.authenticated = 1;
36 dmcontrol.version = 1;
37 dmcontrol.authbusy = 0;
38 dmcontrol.authtype = dmcontrol.AUTHTYPE_NOAUTH;
39 abstractcs = datacount << DMI_ABSTRACTCS_DATACOUNT_OFFSET;
40 }
41
42 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
43 {
44 addr = DEBUG_START + addr;
45
46 if (addr >= DEBUG_ROM_ENTRY && addr <= DEBUG_ROM_CODE) {
47 memcpy(bytes, debug_rom_entry + addr - DEBUG_ROM_ENTRY, len);
48 return true;
49 }
50
51 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
52 PRIx64 "\n", len, addr);
53
54 return false;
55 }
56
57 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
58 {
59 addr = DEBUG_START + addr;
60
61 if (addr & (len-1)) {
62 fprintf(stderr, "ERROR: unaligned store to debug module: %zd bytes at 0x%016"
63 PRIx64 "\n", len, addr);
64 return false;
65 }
66
67 // memcpy(debug_ram + addr - DEBUG_RAM_START, bytes, len);
68
69 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
70 PRIx64 "\n", len, addr);
71 return false;
72 }
73
74 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
75 {
76 uint8_t* base = memory + index * 4;
77 base[0] = value & 0xff;
78 base[1] = (value >> 8) & 0xff;
79 base[2] = (value >> 16) & 0xff;
80 base[3] = (value >> 24) & 0xff;
81 }
82
83 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
84 {
85 uint8_t* base = memory + index * 4;
86 uint32_t value = ((uint32_t) base[0]) |
87 (((uint32_t) base[1]) << 8) |
88 (((uint32_t) base[2]) << 16) |
89 (((uint32_t) base[3]) << 24);
90 return value;
91 }
92
93 processor_t *debug_module_t::current_proc() const
94 {
95 processor_t *proc = NULL;
96 try {
97 proc = sim->get_core(dmcontrol.hartsel);
98 } catch (const std::out_of_range&) {
99 }
100 return proc;
101 }
102
103 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
104 {
105 uint32_t result = 0;
106 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
107 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
108 result = data[address - DMI_DATA0];
109 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
110 result = ibuf[address - DMI_IBUF0];
111 } else {
112 switch (address) {
113 case DMI_DMCONTROL:
114 {
115 processor_t *proc = current_proc();
116 if (proc) {
117 if (proc->halted()) {
118 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_HALTED;
119 } else {
120 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_RUNNING;
121 }
122 dmcontrol.haltreq = proc->halt_request;
123 } else {
124 dmcontrol.hartstatus = dmcontrol.HARTSTATUS_NOTEXIST;
125 }
126 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
127 result = set_field(result, DMI_DMCONTROL_RESET, dmcontrol.reset);
128 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
129 result = set_field(result, DMI_DMCONTROL_HARTSTATUS, dmcontrol.hartstatus);
130 result = set_field(result, DMI_DMCONTROL_HARTSEL, dmcontrol.hartsel);
131 result = set_field(result, DMI_DMCONTROL_AUTHENTICATED, dmcontrol.authenticated);
132 result = set_field(result, DMI_DMCONTROL_AUTHBUSY, dmcontrol.authbusy);
133 result = set_field(result, DMI_DMCONTROL_AUTHTYPE, dmcontrol.authtype);
134 result = set_field(result, DMI_DMCONTROL_VERSION, dmcontrol.version);
135 }
136 break;
137 case DMI_ABSTRACTCS:
138 result = abstractcs;
139 break;
140 case DMI_ACCESSCS:
141 result = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
142 break;
143 default:
144 D(fprintf(stderr, "error\n"));
145 return false;
146 }
147 }
148 D(fprintf(stderr, "0x%x\n", result));
149 *value = result;
150 return true;
151 }
152
153 bool debug_module_t::perform_abstract_command(uint32_t command)
154 {
155 return false;
156 }
157
158 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
159 {
160 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
161 if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
162 data[address - DMI_DATA0] = value;
163 return true;
164 } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
165 ibuf[address - DMI_IBUF0] = value;
166 return true;
167 } else {
168 switch (address) {
169 case DMI_DMCONTROL:
170 {
171 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
172 if (dmcontrol.dmactive) {
173 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
174 dmcontrol.reset = get_field(value, DMI_DMCONTROL_RESET);
175 dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSEL);
176 } else {
177 reset();
178 }
179 processor_t *proc = current_proc();
180 if (proc) {
181 proc->halt_request = dmcontrol.haltreq;
182 }
183 }
184 return true;
185
186 case DMI_ABSTRACTCS:
187 return perform_abstract_command(value);
188 }
189 }
190 return false;
191 }