Skip to content

Commit 11ee6d0

Browse files
authored
Merge pull request #2105 from fk-sc/fk-sc/configurable-datacount
Add configurable datacount for debug module
2 parents 9b136d0 + 5397899 commit 11ee6d0

File tree

3 files changed

+115
-44
lines changed

3 files changed

+115
-44
lines changed

riscv/debug_module.cc

Lines changed: 97 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
#include <algorithm>
2+
#include <array>
13
#include <cassert>
4+
#include <iterator>
5+
#include <limits>
26

37
#include "simif.h"
48
#include "devices.h"
@@ -32,6 +36,25 @@ static unsigned field_width(unsigned n)
3236

3337
///////////////////////// debug_module_t
3438

39+
static bool region_descriptor_comparator(const region_descriptor &lhs,
40+
const region_descriptor &rhs) {
41+
return lhs.addr < rhs.addr;
42+
}
43+
44+
template <typename It>
45+
static bool has_intersection(It begin, It end) {
46+
assert(std::is_sorted(begin, end, region_descriptor_comparator));
47+
48+
// If current interval's end > next interval's start, they intersect
49+
auto intersecion =
50+
std::adjacent_find(begin, end, [](const auto &lhs, const auto &rhs) {
51+
assert(std::numeric_limits<reg_t>::max() - lhs.addr >= lhs.len);
52+
return lhs.addr + lhs.len > rhs.addr;
53+
});
54+
55+
return intersecion != end;
56+
}
57+
3558
debug_module_t::debug_module_t(simif_t *sim, const debug_module_config_t &config) :
3659
config(config),
3760
program_buffer_bytes((config.support_impebreak ? 4 : 0) + 4*config.progbufsize),
@@ -57,11 +80,18 @@ debug_module_t::debug_module_t(simif_t *sim, const debug_module_config_t &config
5780
exit(1);
5881
}
5982

83+
constexpr unsigned max_data_reg = 12;
84+
constexpr unsigned min_data_reg = 1;
85+
if (config.datacount < min_data_reg || config.datacount > max_data_reg) {
86+
fprintf(stderr, "dm-datacount must be between 1 and 12 (got %u)\n", config.datacount);
87+
exit(1);
88+
}
89+
90+
dmdata.resize(config.datacount * dmdata_reg_size);
6091
program_buffer = new uint8_t[program_buffer_bytes];
6192

6293
memset(debug_rom_flags, 0, sizeof(debug_rom_flags));
6394
memset(program_buffer, 0, program_buffer_bytes);
64-
memset(dmdata, 0, sizeof(dmdata));
6595

6696
if (config.support_impebreak) {
6797
program_buffer[4*config.progbufsize] = ebreak();
@@ -78,6 +108,20 @@ debug_module_t::debug_module_t(simif_t *sim, const debug_module_config_t &config
78108
hart_available_state[i] = true;
79109
}
80110

111+
debug_memory_regions = {
112+
region_descriptor{DEBUG_ROM_ENTRY, debug_rom_raw_len, debug_rom_raw},
113+
region_descriptor{DEBUG_ROM_WHERETO, sizeof(debug_rom_whereto), debug_rom_whereto},
114+
region_descriptor{DEBUG_ROM_FLAGS, sizeof(debug_rom_flags), debug_rom_flags},
115+
region_descriptor{debug_data_start, dmdata.size(), dmdata.data()},
116+
region_descriptor{debug_abstract_start, sizeof(debug_abstract), debug_abstract},
117+
region_descriptor{debug_progbuf_start, program_buffer_bytes, program_buffer},
118+
};
119+
120+
std::sort(debug_memory_regions.begin(), debug_memory_regions.end(),
121+
region_descriptor_comparator);
122+
assert(!has_intersection(debug_memory_regions.begin(),
123+
debug_memory_regions.end()));
124+
81125
reset();
82126
}
83127

@@ -100,7 +144,7 @@ void debug_module_t::reset()
100144
dmstatus.version = 2;
101145

102146
memset(&abstractcs, 0, sizeof(abstractcs));
103-
abstractcs.datacount = sizeof(dmdata) / 4;
147+
abstractcs.datacount = config.datacount;
104148
abstractcs.progbufsize = config.progbufsize;
105149

106150
memset(&abstractauto, 0, sizeof(abstractauto));
@@ -122,38 +166,27 @@ void debug_module_t::reset()
122166
challenge = random();
123167
}
124168

169+
static bool belongs_to_range(reg_t access_addr, size_t access_len,
170+
reg_t range_addr, size_t range_len)
171+
{
172+
assert(std::numeric_limits<reg_t>::max() - access_addr >= access_len);
173+
assert(std::numeric_limits<reg_t>::max() - range_addr >= range_len);
174+
return access_addr >= range_addr && (access_addr < range_addr + range_len) &&
175+
((access_addr + access_len) <= (range_addr + range_len));
176+
}
177+
125178
bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
126179
{
127180
addr = DEBUG_START + addr;
128181

129-
if (addr >= DEBUG_ROM_ENTRY &&
130-
(addr + len) <= (DEBUG_ROM_ENTRY + debug_rom_raw_len)) {
131-
memcpy(bytes, debug_rom_raw + addr - DEBUG_ROM_ENTRY, len);
132-
return true;
133-
}
134-
135-
if (addr >= DEBUG_ROM_WHERETO && (addr + len) <= (DEBUG_ROM_WHERETO + 4)) {
136-
memcpy(bytes, debug_rom_whereto + addr - DEBUG_ROM_WHERETO, len);
137-
return true;
138-
}
139-
140-
if (addr >= DEBUG_ROM_FLAGS && ((addr + len) <= DEBUG_ROM_FLAGS + 1024)) {
141-
memcpy(bytes, debug_rom_flags + addr - DEBUG_ROM_FLAGS, len);
142-
return true;
143-
}
144-
145-
if (addr >= debug_abstract_start && ((addr + len) <= (debug_abstract_start + sizeof(debug_abstract)))) {
146-
memcpy(bytes, debug_abstract + addr - debug_abstract_start, len);
147-
return true;
148-
}
149-
150-
if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
151-
memcpy(bytes, dmdata + addr - debug_data_start, len);
152-
return true;
153-
}
182+
const auto interval_ptr =
183+
std::find_if(debug_memory_regions.begin(), debug_memory_regions.end(),
184+
[addr, len](const auto &range) {
185+
return belongs_to_range(addr, len, range.addr, range.len);
186+
});
154187

155-
if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
156-
memcpy(bytes, program_buffer + addr - debug_progbuf_start, len);
188+
if (interval_ptr != debug_memory_regions.end()) {
189+
std::copy_n(std::next(interval_ptr->bytes, addr - interval_ptr->addr), len, bytes);
157190
return true;
158191
}
159192

@@ -163,6 +196,15 @@ bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
163196
return false;
164197
}
165198

199+
static bool handle_range_store(reg_t input_addr, size_t input_len, const uint8_t *bytes,
200+
reg_t range_addr, size_t range_len, uint8_t *data)
201+
{
202+
if (!belongs_to_range(input_addr, input_len, range_addr, range_len))
203+
return false;
204+
std::copy_n(bytes, input_len, std::next(data, input_addr - range_addr));
205+
return true;
206+
}
207+
166208
bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
167209
{
168210
D(
@@ -188,16 +230,11 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
188230

189231
addr = DEBUG_START + addr;
190232

191-
if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
192-
memcpy(dmdata + addr - debug_data_start, bytes, len);
233+
if (handle_range_store(addr, len, bytes, debug_data_start, dmdata.size(), dmdata.data()))
193234
return true;
194-
}
195-
196-
if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
197-
memcpy(program_buffer + addr - debug_progbuf_start, bytes, len);
198235

236+
if (handle_range_store(addr, len, bytes, debug_progbuf_start, program_buffer_bytes, program_buffer))
199237
return true;
200-
}
201238

202239
if (addr == DEBUG_ROM_HALTED) {
203240
assert (len == 4);
@@ -283,6 +320,16 @@ unsigned debug_module_t::sb_access_bits()
283320
return 8 << sbcs.sbaccess;
284321
}
285322

323+
uint8_t *debug_module_t::get_dmdata_checked(size_t required_size)
324+
{
325+
if(dmdata.size() < required_size) {
326+
fprintf(stderr, "dmdata size (%ld) less then required (%ld)\n",
327+
dmdata.size(), required_size);
328+
exit(1);
329+
}
330+
return dmdata.data();
331+
}
332+
286333
void debug_module_t::sb_autoincrement()
287334
{
288335
if (!sbcs.autoincrement || !config.max_sba_data_width)
@@ -392,7 +439,8 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
392439
D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
393440
if (address >= DM_DATA0 && address < DM_DATA0 + abstractcs.datacount) {
394441
unsigned i = address - DM_DATA0;
395-
result = read32(dmdata, i);
442+
assert(dmdata.size() >= 4);
443+
result = read32(get_dmdata_checked(i + 1), i);
396444
if (abstractcs.busy) {
397445
result = -1;
398446
D(fprintf(stderr, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address, i));
@@ -660,6 +708,13 @@ bool debug_module_t::perform_abstract_command()
660708
return true;
661709
}
662710

711+
assert(size < 8);
712+
// Check if register fit in dmdata
713+
if ((1U << size) > dmdata.size()) {
714+
abstractcs.cmderr = CMDERR_NOTSUP;
715+
return true;
716+
}
717+
663718
unsigned i = 0;
664719
if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
665720

@@ -781,10 +836,11 @@ bool debug_module_t::perform_abstract_command()
781836
if (write) {
782837
// Writing V to custom register N will cause future reads of N to
783838
// return V, reads of N-1 will return V-1, etc.
784-
custom_base = read32(dmdata, 0) - custom_number;
839+
assert(dmdata.size() >= 4);
840+
custom_base = read32(get_dmdata_checked(1), 0) - custom_number;
785841
} else {
786-
write32(dmdata, 0, custom_number + custom_base);
787-
write32(dmdata, 1, 0);
842+
write32(get_dmdata_checked(1), 0, custom_number + custom_base);
843+
write32(get_dmdata_checked(2), 1, 0);
788844
}
789845
return true;
790846

@@ -832,7 +888,7 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
832888
if (address >= DM_DATA0 && address < DM_DATA0 + abstractcs.datacount) {
833889
unsigned i = address - DM_DATA0;
834890
if (!abstractcs.busy)
835-
write32(dmdata, address - DM_DATA0, value);
891+
write32(get_dmdata_checked(address - DM_DATA0), address - DM_DATA0, value);
836892

837893
if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
838894
abstractcs.cmderr = CMDERR_BUSY;

riscv/debug_module.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#ifndef _RISCV_DEBUG_MODULE_H
33
#define _RISCV_DEBUG_MODULE_H
44

5-
#include <set>
5+
#include <array>
66
#include <vector>
77

88
#include "abstract_device.h"
@@ -15,6 +15,7 @@ struct debug_module_config_t {
1515
// Size of program_buffer in 32-bit words, as exposed to the rest of the
1616
// world.
1717
unsigned progbufsize = 2;
18+
unsigned datacount = 2;
1819
unsigned max_sba_data_width = 0;
1920
bool require_authentication = false;
2021
unsigned abstract_rti = 0;
@@ -99,6 +100,13 @@ struct hart_debug_state_t {
99100
uint8_t haltgroup;
100101
};
101102

103+
// structure to describe mmio region
104+
struct region_descriptor {
105+
reg_t addr; // 1st addr in a range
106+
size_t len; // range size
107+
const uint8_t *bytes; // data
108+
};
109+
102110
class debug_module_t : public abstract_device_t
103111
{
104112
public:
@@ -131,7 +139,6 @@ class debug_module_t : public abstract_device_t
131139
void proc_reset(unsigned id);
132140

133141
private:
134-
static const unsigned datasize = 2;
135142
debug_module_config_t config;
136143
// Actual size of the program buffer, which is 1 word bigger than we let on
137144
// to implement the implicit ebreak at the end.
@@ -150,7 +157,8 @@ class debug_module_t : public abstract_device_t
150157
uint8_t debug_rom_whereto[4];
151158
uint8_t debug_abstract[debug_abstract_size * 4];
152159
uint8_t *program_buffer;
153-
uint8_t dmdata[datasize * 4];
160+
static constexpr unsigned dmdata_reg_size = 4;
161+
std::vector<uint8_t> dmdata;
154162

155163
std::vector<hart_debug_state_t> hart_state;
156164
uint8_t debug_rom_flags[1024];
@@ -174,6 +182,8 @@ class debug_module_t : public abstract_device_t
174182

175183
unsigned sb_access_bits();
176184

185+
uint8_t *get_dmdata_checked(size_t required_size);
186+
177187
dmcontrol_t dmcontrol;
178188
dmstatus_t dmstatus;
179189
abstractcs_t abstractcs;
@@ -206,6 +216,8 @@ class debug_module_t : public abstract_device_t
206216
bool hart_available(unsigned hart_id) const;
207217

208218
unsigned sb_read_wait, sb_write_wait;
219+
220+
std::array<region_descriptor, 6> debug_memory_regions;
209221
};
210222

211223
#endif

spike_main/spike.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static void help(int exit_code = 1)
7171
fprintf(stderr, " --real-time-clint Increment clint time at real-time rate\n");
7272
fprintf(stderr, " --triggers=<n> Number of supported triggers [default 4]\n");
7373
fprintf(stderr, " --dm-progsize=<words> Progsize for the debug module [default 2]\n");
74+
fprintf(stderr, " --dm-datacount=<n> Number of data registers available for the debug module [default 2]\n");
7475
fprintf(stderr, " --dm-sba=<bits> Debug system bus access supports up to "
7576
"<bits> wide accesses [default 0]\n");
7677
fprintf(stderr, " --dm-auth Debug module requires debugger to authenticate\n");
@@ -413,6 +414,8 @@ int main(int argc, char** argv)
413414
});
414415
parser.option(0, "dm-progsize", 1,
415416
[&](const char* s){dm_config.progbufsize = atoul_safe(s);});
417+
parser.option(0, "dm-datacount", 1,
418+
[&](const char* s){dm_config.datacount = atoul_safe(s);});
416419
parser.option(0, "dm-no-impebreak", 0,
417420
[&](const char UNUSED *s){dm_config.support_impebreak = false;});
418421
parser.option(0, "dm-sba", 1,

0 commit comments

Comments
 (0)