@@ -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,95 @@ 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+ const unsigned int scan_bits = batch -> fields -> num_bits ;
202+ assert (scan_bits == (unsigned int )riscv_get_dmi_scan_length (batch -> target ));
203+ const unsigned int abits = scan_bits - DTM_DMI_OP_LENGTH
204+ - DTM_DMI_DATA_LENGTH ;
205+
206+ /* Determine the "op" and "address" of the scan that preceded the first
207+ * executed scan.
208+ * FIXME: The code here assumes that there were no DMI operations between
209+ * the last execution of the batch and the current one.
210+ * Caching the info about the last executed DMI scan in "dm013_info_t"
211+ * would be a more robust solution.
212+ */
213+ bool last_scan_was_read = false;
214+ uint32_t last_scan_address = -1 /* to silence maybe-uninitialized */ ;
215+ if (start_idx > 0 ) {
216+ const struct scan_field * const field = & batch -> fields [start_idx - 1 ];
217+ assert (field -> out_value );
218+ last_scan_was_read = buf_get_u32 (field -> out_value , DTM_DMI_OP_OFFSET ,
219+ DTM_DMI_OP_LENGTH ) == DTM_DMI_OP_READ ;
220+ last_scan_address = buf_get_u32 (field -> out_value ,
221+ DTM_DMI_ADDRESS_OFFSET , abits );
215222 }
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 );
223+
224+ /* Decode and log every executed scan */
225+ for (size_t i = start_idx ; i < batch -> used_scans ; ++ i ) {
226+ static const char * const op_string [] = {"-" , "r" , "w" , "?" };
227+ const int delay = get_delay (batch , i , delays , resets_delays ,
228+ reset_delays_after );
229+ const struct scan_field * const field = & batch -> fields [i ];
230+
231+ assert (field -> out_value );
232+ const unsigned int out_op = buf_get_u32 (field -> out_value ,
233+ DTM_DMI_OP_OFFSET , DTM_DMI_OP_LENGTH );
234+ const uint32_t out_data = buf_get_u32 (field -> out_value ,
235+ DTM_DMI_DATA_OFFSET , DTM_DMI_DATA_LENGTH );
236+ const uint32_t out_address = buf_get_u32 (field -> out_value ,
237+ DTM_DMI_ADDRESS_OFFSET , abits );
238+ if (field -> in_value ) {
239+ static const char * const status_string [] = {
240+ "+" , "?" , "F" , "b"
241+ };
242+ const unsigned int in_op = buf_get_u32 (field -> in_value ,
243+ DTM_DMI_OP_OFFSET , DTM_DMI_OP_LENGTH );
244+ const uint32_t in_data = buf_get_u32 (field -> in_value ,
245+ DTM_DMI_DATA_OFFSET , DTM_DMI_DATA_LENGTH );
246+ const uint32_t in_address = buf_get_u32 (field -> in_value ,
247+ DTM_DMI_ADDRESS_OFFSET , abits );
248+
249+ LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32
250+ " -> %s %08" PRIx32 " @%02" PRIx32 "; %di" ,
251+ field -> num_bits , op_string [out_op ], out_data , out_address ,
252+ status_string [in_op ], in_data , in_address , delay );
253+
254+ if (last_scan_was_read && in_op == DTM_DMI_OP_SUCCESS )
255+ log_dmi_decoded (batch , /*write*/ false,
256+ last_scan_address , in_data );
257+ } else {
258+ LOG_DEBUG ("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di" ,
259+ field -> num_bits , op_string [out_op ], out_data , out_address ,
260+ delay );
261+ }
262+
263+ if (out_op == DTM_DMI_OP_WRITE )
264+ log_dmi_decoded (batch , /*write*/ true, out_address ,
265+ out_data );
266+
267+ last_scan_was_read = out_op == DTM_DMI_OP_READ ;
268+ last_scan_address = out_address ;
220269 }
221270}
222271
@@ -225,6 +274,7 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
225274 size_t reset_delays_after )
226275{
227276 assert (batch -> used_scans );
277+ assert (start_idx < batch -> used_scans );
228278 assert (batch -> last_scan == RISCV_SCAN_TYPE_NOP );
229279 assert (!batch -> was_run || riscv_batch_was_scan_busy (batch , start_idx ));
230280 assert (start_idx == 0 || !riscv_batch_was_scan_busy (batch , start_idx - 1 ));
@@ -235,17 +285,16 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
235285 LOG_TARGET_DEBUG (batch -> target , "Running batch of scans [%zu, %zu)" ,
236286 start_idx , batch -> used_scans );
237287
288+ unsigned int delay = 0 /* to silence maybe-uninitialized */ ;
238289 for (size_t i = start_idx ; i < batch -> used_scans ; ++ i ) {
239290 if (bscan_tunnel_ir_width != 0 )
240291 riscv_add_bscan_tunneled_scan (batch -> target , batch -> fields + i , batch -> bscan_ctxt + i );
241292 else
242293 jtag_add_dr_scan (batch -> target -> tap , 1 , batch -> fields + i , TAP_IDLE );
243294
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 )
295+ delay = get_delay (batch , i , delays , resets_delays ,
296+ reset_delays_after );
297+ if (delay > 0 )
249298 jtag_add_runtest (delay , TAP_IDLE );
250299 }
251300
@@ -266,13 +315,9 @@ int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx,
266315 }
267316 }
268317
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-
318+ log_batch (batch , start_idx , delays , resets_delays , reset_delays_after );
274319 batch -> was_run = true;
275- batch -> last_scan_delay = get_delay ( batch , batch -> used_scans - 1 , delays ) ;
320+ batch -> last_scan_delay = delay ;
276321 return ERROR_OK ;
277322}
278323
0 commit comments