@@ -132,18 +132,22 @@ static void add_idle_before_batch(const struct riscv_batch *batch, size_t start_
132132}
133133
134134static int get_delay (const struct riscv_batch * batch , size_t scan_idx ,
135- const struct riscv_scan_delays * delays )
135+ const struct riscv_scan_delays * delays , bool resets_delays ,
136+ size_t reset_delays_after )
136137{
137138 assert (batch );
138139 assert (scan_idx < batch -> used_scans );
140+ const bool delays_were_reset = resets_delays
141+ && (scan_idx >= reset_delays_after );
139142 const enum riscv_scan_delay_class delay_class =
140143 batch -> delay_classes [scan_idx ];
141144 const unsigned int delay = riscv_scan_get_delay (delays , delay_class );
142145 assert (delay <= INT_MAX );
143- return delay ;
146+ return delays_were_reset ? 0 : delay ;
144147}
145148
146- static unsigned int decode_dmi (const struct target * target , char * text , uint32_t address , uint32_t data )
149+ static unsigned int decode_dmi (const struct riscv_batch * batch , char * text ,
150+ uint32_t address , uint32_t data )
147151{
148152 static const struct {
149153 uint32_t address ;
@@ -157,7 +161,8 @@ static unsigned int decode_dmi(const struct target *target, char *text, uint32_t
157161 };
158162
159163 for (unsigned int i = 0 ; i < ARRAY_SIZE (description ); i ++ ) {
160- if (riscv_get_dmi_address (target , description [i ].address ) == address ) {
164+ if (riscv_get_dmi_address (batch -> target , description [i ].address )
165+ == address ) {
161166 const riscv_debug_reg_ctx_t context = {
162167 .XLEN = { .value = 0 , .is_set = false },
163168 .DXLEN = { .value = 0 , .is_set = false },
@@ -172,51 +177,85 @@ static unsigned int decode_dmi(const struct target *target, char *text, uint32_t
172177 return 0 ;
173178}
174179
175- static void riscv_log_dmi_scan (const struct target * target , int idle ,
176- const struct scan_field * field )
180+ static void log_dmi_decoded (const struct riscv_batch * batch , bool write ,
181+ uint32_t address , uint32_t data )
177182{
178- static const char * const op_string [] = {"-" , "r" , "w" , "?" };
179- static const char * const status_string [] = {"+" , "?" , "F" , "b" };
183+ const size_t size = decode_dmi (batch , /* text */ NULL , address , data ) + 1 ;
184+ char * const decoded = malloc (size );
185+ if (!decoded ) {
186+ LOG_ERROR ("Not enough memory to allocate %zu bytes." , size );
187+ return ;
188+ }
189+ decode_dmi (batch , decoded , address , data );
190+ LOG_DEBUG ("%s: %s" , write ? "write" : "read" , decoded );
191+ free (decoded );
192+ }
180193
194+ static void log_batch (const struct riscv_batch * batch , size_t start_idx ,
195+ const struct riscv_scan_delays * delays , bool resets_delays ,
196+ size_t reset_delays_after )
197+ {
181198 if (debug_level < LOG_LVL_DEBUG )
182199 return ;
183200
184- assert (field -> out_value );
185- const uint64_t out = buf_get_u64 (field -> out_value , 0 , field -> num_bits );
186- const unsigned int out_op = get_field (out , DTM_DMI_OP );
187- const uint32_t out_data = get_field (out , DTM_DMI_DATA );
188- const uint32_t out_address = out >> DTM_DMI_ADDRESS_OFFSET ;
189-
190- if (field -> in_value ) {
191- const uint64_t in = buf_get_u64 (field -> in_value , 0 , field -> num_bits );
192- const unsigned int in_op = get_field (in , DTM_DMI_OP );
193- const uint32_t in_data = get_field (in , DTM_DMI_DATA );
194- const uint32_t in_address = in >> DTM_DMI_ADDRESS_OFFSET ;
195-
196- LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32 " -> %s %08" PRIx32 " @%02" PRIx32 "; %di" ,
197- field -> num_bits , op_string [out_op ], out_data , out_address ,
198- status_string [in_op ], in_data , in_address , idle );
199-
200- if (in_op == DTM_DMI_OP_SUCCESS ) {
201- char in_decoded [decode_dmi (target , NULL , in_address , in_data ) + 1 ];
202- decode_dmi (target , in_decoded , in_address , in_data );
203- /* FIXME: The current code assumes that the hardware
204- * provides the read address in the dmi.address field
205- * when returning the dmi.data. That is however not
206- * required by the spec, and therefore not guaranteed.
207- * See https://github.com/riscv-collab/riscv-openocd/issues/1043
208- */
209- LOG_DEBUG ("read: %s" , in_decoded );
210- }
211- } else {
212- LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di" ,
213- field -> num_bits , op_string [out_op ], out_data , out_address ,
214- idle );
201+ bool reads = false;
202+ uint32_t last_address = -1 /* to silence maybe-uninitialized */ ;
203+ if (start_idx > 0 ) {
204+ const struct scan_field * const field = & batch -> fields [start_idx - 1 ];
205+ assert (field -> out_value );
206+ reads = buf_get_u32 (field -> out_value , DTM_DMI_OP_OFFSET ,
207+ DTM_DMI_OP_LENGTH ) == DTM_DMI_OP_READ ;
208+ const unsigned int abits = field -> num_bits - DTM_DMI_OP_LENGTH
209+ - DTM_DMI_DATA_LENGTH ;
210+ last_address = buf_get_u32 (field -> out_value ,
211+ DTM_DMI_ADDRESS_OFFSET , abits );
215212 }
216- if (out_op == DTM_DMI_OP_WRITE ) {
217- char out_decoded [decode_dmi (target , NULL , out_address , out_data ) + 1 ];
218- decode_dmi (target , out_decoded , out_address , out_data );
219- LOG_DEBUG ("write: %s" , out_decoded );
213+ for (size_t i = start_idx ; i < batch -> used_scans ; ++ i ) {
214+ static const char * const op_string [] = {"-" , "r" , "w" , "?" };
215+ const int delay = get_delay (batch , i , delays , resets_delays ,
216+ reset_delays_after );
217+ const struct scan_field * const field = & batch -> fields [i ];
218+
219+ assert (field -> out_value );
220+ const unsigned int out_op = buf_get_u32 (field -> out_value ,
221+ DTM_DMI_OP_OFFSET , DTM_DMI_OP_LENGTH );
222+ const uint32_t out_data = buf_get_u32 (field -> out_value ,
223+ DTM_DMI_DATA_OFFSET , DTM_DMI_DATA_LENGTH );
224+ const unsigned int abits = field -> num_bits - DTM_DMI_OP_LENGTH
225+ - DTM_DMI_DATA_LENGTH ;
226+ const uint32_t out_address = buf_get_u32 (field -> out_value ,
227+ DTM_DMI_ADDRESS_OFFSET , abits );
228+ if (field -> in_value ) {
229+ static const char * const status_string [] = {
230+ "+" , "?" , "F" , "b"
231+ };
232+ const unsigned int in_op = buf_get_u32 (field -> in_value ,
233+ DTM_DMI_OP_OFFSET , DTM_DMI_OP_LENGTH );
234+ const uint32_t in_data = buf_get_u32 (field -> in_value ,
235+ DTM_DMI_DATA_OFFSET , DTM_DMI_DATA_LENGTH );
236+ const uint32_t in_address = buf_get_u32 (field -> in_value ,
237+ DTM_DMI_ADDRESS_OFFSET , abits );
238+
239+ LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32
240+ " -> %s %08" PRIx32 " @%02" PRIx32 "; %di" ,
241+ field -> num_bits , op_string [out_op ], out_data , out_address ,
242+ status_string [in_op ], in_data , in_address , delay );
243+
244+ if (reads && in_op == DTM_DMI_OP_SUCCESS )
245+ log_dmi_decoded (batch , /*write*/ false,
246+ last_address , in_data );
247+ } else {
248+ LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di" ,
249+ field -> num_bits , op_string [out_op ], out_data , out_address ,
250+ delay );
251+ }
252+
253+ if (out_op == DTM_DMI_OP_WRITE )
254+ log_dmi_decoded (batch , /*write*/ true, out_address ,
255+ out_data );
256+
257+ reads = out_op == DTM_DMI_OP_READ ;
258+ last_address = out_address ;
220259 }
221260}
222261
@@ -225,6 +264,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
225264 size_t reset_delays_after )
226265{
227266 assert (batch -> used_scans );
267+ assert (start_idx < batch -> used_scans );
228268 assert (batch -> last_scan == RISCV_SCAN_TYPE_NOP );
229269 assert (!batch -> was_run || riscv_batch_was_scan_busy (batch , start_idx ));
230270 assert (start_idx == 0 || !riscv_batch_was_scan_busy (batch , start_idx - 1 ));
@@ -235,18 +275,16 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
235275 LOG_TARGET_DEBUG (batch -> target , "Running batch of scans [%zu, %zu)" ,
236276 start_idx , batch -> used_scans );
237277
278+ unsigned int delay = 0 /* to silence maybe-uninitialized */ ;
238279 for (size_t i = start_idx ; i < batch -> used_scans ; ++ i ) {
239280 if (bscan_tunnel_ir_width != 0 )
240281 riscv_add_bscan_tunneled_scan (batch -> target , batch -> fields + i , batch -> bscan_ctxt + i );
241282 else
242283 jtag_add_dr_scan (batch -> target -> tap , 1 , batch -> fields + i , TAP_IDLE );
243284
244- const bool delays_were_reset = resets_delays
245- && (i >= reset_delays_after );
246- const int delay = get_delay (batch , i , delays );
247-
248- if (!delays_were_reset )
249- jtag_add_runtest (delay , TAP_IDLE );
285+ delay = get_delay (batch , i , delays , resets_delays ,
286+ reset_delays_after );
287+ jtag_add_runtest (delay , TAP_IDLE );
250288 }
251289
252290 keep_alive ();
@@ -266,13 +304,9 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
266304 }
267305 }
268306
269- for (size_t i = start_idx ; i < batch -> used_scans ; ++ i ) {
270- const int delay = get_delay (batch , i , delays );
271- riscv_log_dmi_scan (batch -> target , delay , batch -> fields + i );
272- }
273-
307+ log_batch (batch , start_idx , delays , resets_delays , reset_delays_after );
274308 batch -> was_run = true;
275- batch -> last_scan_delay = get_delay ( batch , batch -> used_scans - 1 , delays ) ;
309+ batch -> last_scan_delay = delay ;
276310 return ERROR_OK ;
277311}
278312
0 commit comments