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+
3558debug_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+
125178bool 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+
166208bool 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+
286333void 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, " \n dmi_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;
0 commit comments