1 /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
2 /*----------------------------------------------------------------------------
3 * Copyright 2020-2021 Cadence Design Systems, Inc.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 *----------------------------------------------------------------------------
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *----------------------------------------------------------------------------
29 * @brief the virtual debug interface provides a connection between a sw debugger
30 * and the simulated, emulated core over a soft connection, implemented by DPI
31 * The vdebug debug driver currently supports JTAG transport
32 * TODO: implement support and test big endian platforms
41 #define WIN32_LEAN_AND_MEAN
45 #include <unistd.h> /* close */
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
50 #ifdef HAVE_ARPA_INET_H
51 #include <arpa/inet.h>
68 #include "jtag/interface.h"
69 #include "jtag/commands.h"
70 #include "transport/transport.h"
71 #include "helper/time_support.h"
72 #include "helper/replacements.h"
73 #include "helper/log.h"
76 #define VD_BUFFER_LEN 4024
77 #define VD_CHEADER_LEN 24
78 #define VD_SHEADER_LEN 16
80 #define VD_MAX_MEMORIES 4
81 #define VD_POLL_INTERVAL 500
82 #define VD_SCALE_PSTOMS 1000000000
85 * @brief List of transactor types
88 VD_BFM_JTDP
= 0x0001, /* transactor DAP JTAG DP */
89 VD_BFM_SWDP
= 0x0002, /* transactor DAP SWD DP */
90 VD_BFM_AHB
= 0x0003, /* transactor AMBA AHB */
91 VD_BFM_APB
= 0x0004, /* transactor AMBA APB */
92 VD_BFM_AXI
= 0x0005, /* transactor AMBA AXI */
93 VD_BFM_JTAG
= 0x0006, /* transactor serial JTAG */
94 VD_BFM_SWD
= 0x0007, /* transactor serial SWD */
98 * @brief List of signals that can be read or written by the debugger
101 VD_SIG_TCK
= 0x0001, /* JTAG clock; tclk */
102 VD_SIG_TDI
= 0x0002, /* JTAG TDI; tdi */
103 VD_SIG_TMS
= 0x0004, /* JTAG TMS; tms */
104 VD_SIG_RESET
= 0x0008, /* DUT reset; rst */
105 VD_SIG_TRST
= 0x0010, /* JTAG Reset; trstn */
106 VD_SIG_TDO
= 0x0020, /* JTAG TDO; tdo */
107 VD_SIG_POWER
= 0x0100, /* BFM power; bfm_up */
108 VD_SIG_TCKDIV
= 0x0200, /* JTAG clock divider; tclkdiv */
109 VD_SIG_BUF
= 0x1000, /* memory buffer; mem */
113 * @brief List of errors
116 VD_ERR_NONE
= 0x0000, /* no error */
117 VD_ERR_NOT_IMPL
= 0x0100, /* feature not implemented */
118 VD_ERR_USAGE
= 0x0101, /* incorrect usage */
119 VD_ERR_PARAM
= 0x0102, /* incorrect parameter */
120 VD_ERR_CONFIG
= 0x0107, /* incorrect configuration */
121 VD_ERR_NO_MEMORY
= 0x0104, /* out of memory */
122 VD_ERR_SHM_OPEN
= 0x010a, /* cannot open shared memory */
123 VD_ERR_SHM_MAP
= 0x010b, /* cannot map shared memory */
124 VD_ERR_SOC_OPEN
= 0x011a, /* cannot open socket */
125 VD_ERR_SOC_OPT
= 0x011b, /* cannot set socket option */
126 VD_ERR_SOC_ADDR
= 0x011c, /* cannot resolve host address */
127 VD_ERR_SOC_CONN
= 0x011d, /* cannot connect to host */
128 VD_ERR_SOC_SEND
= 0x011e, /* error sending data on socket */
129 VD_ERR_SOC_RECV
= 0x011f, /* error receiving data from socket */
130 VD_ERR_LOCKED
= 0x0202, /* device locked */
131 VD_ERR_NOT_RUN
= 0x0204, /* transactor not running */
132 VD_ERR_NOT_OPEN
= 0x0205, /* transactor not open/connected */
133 VD_ERR_LICENSE
= 0x0206, /* cannot check out the license */
134 VD_ERR_VERSION
= 0x0207, /* transactor version mismatch */
135 VD_ERR_TIME_OUT
= 0x0301, /* time out, waiting */
136 VD_ERR_NO_POWER
= 0x0302, /* power out error */
137 VD_ERR_BUS_ERROR
= 0x0304, /* bus protocol error, like pslverr */
138 VD_ERR_NO_ACCESS
= 0x0306, /* no access to an object */
139 VD_ERR_INV_HANDLE
= 0x0307, /* invalid object handle */
140 VD_ERR_INV_SCOPE
= 0x0308, /* invalid scope */
146 VD_CMD_CONNECT
= 0x04,
147 VD_CMD_DISCONNECT
= 0x05,
149 VD_CMD_SIGSET
= 0x0a,
150 VD_CMD_SIGGET
= 0x0b,
151 VD_CMD_JTAGCLOCK
= 0x0f,
152 VD_CMD_JTAGSHTAP
= 0x1a,
153 VD_CMD_MEMOPEN
= 0x21,
154 VD_CMD_MEMCLOSE
= 0x22,
155 VD_CMD_MEMWRITE
= 0x23,
165 struct { /* VD_CHEADER_LEN written by client */
166 uint8_t cmd
; /* 000; command */
167 uint8_t type
; /* 001; interface type */
168 uint16_t waddr
; /* 002; write pointer */
169 uint16_t wbytes
; /* 004; data bytes */
170 uint16_t rbytes
; /* 006; data bytes to read */
171 uint16_t wwords
; /* 008; data words */
172 uint16_t rwords
; /* 00a; data words to read */
173 uint32_t rwdata
; /* 00c; read/write data */
174 uint32_t offset
; /* 010; address offset */
175 uint16_t offseth
; /* 014; address offset 47:32 */
176 uint16_t wid
; /* 016; request id*/
179 uint8_t wd8
[VD_BUFFER_LEN
];
180 uint16_t wd16
[VD_BUFFER_LEN
/ 2];
181 uint32_t wd32
[VD_BUFFER_LEN
/ 4];
182 uint64_t wd64
[VD_BUFFER_LEN
/ 8];
184 struct { /* VD_SHEADER_LEN written by server */
185 uint16_t rid
; /* fd0: request id read */
186 uint16_t awords
; /* fd2: actual data words read back */
187 int32_t status
; /* fd4; */
188 uint64_t duttime
; /* fd8; */
191 uint8_t rd8
[VD_BUFFER_LEN
];
192 uint16_t rd16
[VD_BUFFER_LEN
/ 2];
193 uint32_t rd32
[VD_BUFFER_LEN
/ 4];
194 uint64_t rd64
[VD_BUFFER_LEN
/ 8];
196 uint32_t state
; /* 1f98; connection state */
197 uint32_t count
; /* 1f9c; */
198 uint8_t dummy
[96]; /* 1fa0; 48+40B+8B; */
212 uint32_t mem_base
[VD_MAX_MEMORIES
];
213 uint32_t mem_size
[VD_MAX_MEMORIES
];
214 uint32_t mem_width
[VD_MAX_MEMORIES
];
215 uint32_t mem_depth
[VD_MAX_MEMORIES
];
216 uint16_t server_port
;
217 uint32_t poll_cycles
;
222 char server_name
[32];
224 char mem_path
[VD_MAX_MEMORIES
][128];
237 static struct vd_shm
*pbuf
;
238 static struct vd_client vdc
;
240 static int vdebug_socket_error(void)
243 return WSAGetLastError();
249 static int vdebug_socket_open(char *server_addr
, uint32_t port
)
253 uint32_t buflen
= sizeof(struct vd_shm
); /* size of the send and rcv buffer */
254 struct addrinfo
*ainfo
= NULL
;
255 struct addrinfo ahint
= { 0, AF_INET
, SOCK_STREAM
, 0, 0, NULL
, NULL
, NULL
};
258 hsock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
);
259 if (hsock
== INVALID_SOCKET
)
260 rc
= vdebug_socket_error();
262 uint32_t rcvwat
= VD_SHEADER_LEN
; /* size of the rcv header, as rcv min watermark */
263 hsock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
);
266 else if (setsockopt(hsock
, SOL_SOCKET
, SO_RCVLOWAT
, &rcvwat
, sizeof(rcvwat
)) < 0)
269 else if (setsockopt(hsock
, SOL_SOCKET
, SO_SNDBUF
, (const char *)&buflen
, sizeof(buflen
)) < 0)
270 rc
= vdebug_socket_error();
271 else if (setsockopt(hsock
, SOL_SOCKET
, SO_RCVBUF
, (const char *)&buflen
, sizeof(buflen
)) < 0)
272 rc
= vdebug_socket_error();
275 LOG_ERROR("socket_open: cannot set socket option, error %d", rc
);
276 } else if (getaddrinfo(server_addr
, NULL
, &ahint
, &ainfo
) != 0) {
277 LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr
, vdebug_socket_error());
278 rc
= VD_ERR_SOC_ADDR
;
280 ((struct sockaddr_in
*)(ainfo
->ai_addr
))->sin_port
= htons(port
);
281 if (connect(hsock
, ainfo
->ai_addr
, sizeof(struct sockaddr
)) < 0) {
282 LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr
, port
, vdebug_socket_error());
283 rc
= VD_ERR_SOC_CONN
;
298 static int vdebug_socket_receive(int hsock
, struct vd_shm
*pmem
)
302 int offset
= (uint8_t *)&pmem
->rid
- &pmem
->cmd
;
303 int to_receive
= VD_SHEADER_LEN
+ pmem
->rbytes
;
304 char *pb
= (char *)pmem
;
307 rc
= recv(hsock
, pb
+ offset
, to_receive
, 0);
309 LOG_WARNING("socket_receive: recv failed, error %d", rc
< 0 ? vdebug_socket_error() : 0);
314 LOG_DEBUG_IO("socket_receive: received %d, to receive %d", rc
, to_receive
);
316 } while (to_receive
);
321 static int vdebug_socket_send(int hsock
, struct vd_shm
*pmem
)
323 int rc
= send(hsock
, (const char *)&pmem
->cmd
, VD_CHEADER_LEN
+ pmem
->wbytes
, 0);
325 LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error());
327 LOG_DEBUG_IO("socket_send: sent %d, to send 0", rc
);
332 static uint32_t vdebug_wait_server(int hsock
, struct vd_shm
*pmem
)
335 return VD_ERR_SOC_OPEN
;
336 int st
= vdebug_socket_send(hsock
, pmem
);
338 return VD_ERR_SOC_SEND
;
340 int rd
= vdebug_socket_receive(hsock
, pmem
);
342 return VD_ERR_SOC_RECV
;
344 int rc
= pmem
->status
;
345 LOG_DEBUG_IO("wait_server: cmd %02" PRIx8
" done, sent %d, rcvd %d, status %d",
346 pmem
->cmd
, st
, rd
, rc
);
351 int vdebug_run_jtag_queue(int hsock
, struct vd_shm
*pm
, unsigned int count
)
353 uint8_t num_pre
, num_post
, tdi
, tms
;
354 unsigned int num
, anum
, bytes
, hwords
, words
;
355 unsigned int req
, waddr
, rwords
;
359 struct vd_jtag_hdr
*hdr
;
361 req
= 0; /* beginning of request */
364 pm
->wbytes
= pm
->wwords
* vdc
.buf_width
;
365 pm
->rbytes
= pm
->rwords
* vdc
.buf_width
;
367 rc
= vdebug_wait_server(hsock
, pm
);
368 while (!rc
&& (req
< count
)) { /* loop over requests to read data and print out */
369 hdr
= (struct vd_jtag_hdr
*)&pm
->wd8
[waddr
* 4];
374 num_post
= hdr
->post
;
376 num
= anum
- num_pre
- num_post
+ 1;
378 num
= anum
- num_pre
;
379 bytes
= (num
+ 7) / 8;
380 vdc
.trans_last
= (req
+ 1) < count
? 0 : 1;
381 vdc
.trans_first
= waddr
? 0 : 1;
382 if (hdr
->cmd
== 3) { /* read */
384 for (unsigned int j
= 0; j
< bytes
; j
++) {
385 tdo
[j
] = (pm
->rd8
[rwords
* 8 + j
] >> num_pre
) | (pm
->rd8
[rwords
* 8 + j
+ 1] << (8 - num_pre
));
386 LOG_DEBUG_IO("%04x D0[%02x]:%02x", pm
->wid
- count
+ req
, j
, tdo
[j
]);
388 rwords
+= words
; /* read data offset */
392 waddr
+= sizeof(struct vd_jtag_hdr
) / 4; /* waddr past header */
393 tdi
= (pm
->wd8
[waddr
* 4] >> num_pre
) | (pm
->wd8
[waddr
* 4 + 1] << (8 - num_pre
));
394 tms
= (pm
->wd8
[waddr
* 4 + 4] >> num_pre
) | (pm
->wd8
[waddr
* 4 + 4 + 1] << (8 - num_pre
));
395 LOG_DEBUG("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x",
396 pm
->wid
- count
+ req
, num
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15),
397 waddr
- 2, tdi
, tms
, (tdo
? tdo
[0] : 0xdd));
398 waddr
+= hwords
* 2; /* start of next request */
403 LOG_ERROR("0x%x executing transaction", rc
);
408 vdc
.targ_time
+= (uint32_t)(te
- ts
);
409 pm
->offseth
= 0; /* reset buffer write address */
417 static int vdebug_open(int hsock
, struct vd_shm
*pm
, const char *path
,
418 uint8_t type
, uint32_t period_ps
, uint32_t sig_mask
)
420 int rc
= VD_ERR_NOT_OPEN
;
422 pm
->cmd
= VD_CMD_OPEN
;
423 pm
->wid
= VD_VERSION
; /* client version */
428 rc
= vdebug_wait_server(hsock
, pm
);
429 if (rc
!= 0) { /* communication problem */
430 LOG_ERROR("0x%x connecting to server", rc
);
431 } else if (pm
->rid
< pm
->wid
) {
432 LOG_ERROR("server version %d too old for the client %d", pm
->rid
, pm
->wid
);
433 pm
->cmd
= VD_CMD_CLOSE
; /* let server close the connection */
434 vdebug_wait_server(hsock
, pm
);
437 pm
->cmd
= VD_CMD_CONNECT
;
438 pm
->type
= type
; /* BFM type to connect to, here JTAG */
439 pm
->rwdata
= sig_mask
| VD_SIG_BUF
| (VD_SIG_BUF
<< 16);
440 pm
->wbytes
= strlen(path
) + 1;
442 pm
->wid
= 0; /* reset wid for transaction ID */
445 memcpy(pm
->wd8
, path
, pm
->wbytes
+ 1);
446 rc
= vdebug_wait_server(hsock
, pm
);
447 vdc
.sig_read
= pm
->rwdata
>> 16; /* signal read mask */
448 vdc
.sig_write
= pm
->rwdata
; /* signal write mask */
449 vdc
.bfm_period
= period_ps
;
450 vdc
.buf_width
= pm
->rd32
[0] / 8;/* access width in bytes */
451 vdc
.addr_bits
= pm
->rd32
[2]; /* supported address bits */
455 LOG_ERROR("0x%x connecting to BFM %s", rc
, path
);
459 LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x",
460 path
, type
, vdc
.bfm_period
, VD_BUFFER_LEN
/ vdc
.buf_width
,
461 vdc
.buf_width
, vdc
.sig_read
, vdc
.sig_write
);
466 static int vdebug_close(int hsock
, struct vd_shm
*pm
, uint8_t type
)
468 pm
->cmd
= VD_CMD_DISCONNECT
;
469 pm
->type
= type
; /* BFM type, here JTAG */
474 vdebug_wait_server(hsock
, pm
);
475 pm
->cmd
= VD_CMD_CLOSE
;
476 pm
->wid
= VD_VERSION
; /* client version */
481 vdebug_wait_server(hsock
, pm
);
482 LOG_DEBUG("type %0x", type
);
487 static int vdebug_wait(int hsock
, struct vd_shm
*pm
, uint32_t cycles
)
490 pm
->cmd
= VD_CMD_WAIT
;
493 pm
->rwdata
= cycles
; /* clock sycles to wait */
494 int rc
= vdebug_wait_server(hsock
, pm
);
496 LOG_ERROR("0x%x waiting %" PRIx32
" cycles", rc
, cycles
);
499 LOG_DEBUG("%d cycles", cycles
);
505 static int vdebug_sig_set(int hsock
, struct vd_shm
*pm
, uint32_t write_mask
, uint32_t value
)
507 pm
->cmd
= VD_CMD_SIGSET
;
510 pm
->rwdata
= (write_mask
<< 16) | (value
& 0xffff); /* mask and value of signals to set */
511 int rc
= vdebug_wait_server(hsock
, pm
);
513 LOG_ERROR("0x%x setting signals %04" PRIx32
, rc
, write_mask
);
517 LOG_DEBUG("setting signals %04" PRIx32
" to %04" PRIx32
, write_mask
, value
);
522 static int vdebug_jtag_clock(int hsock
, struct vd_shm
*pm
, uint32_t value
)
524 pm
->cmd
= VD_CMD_JTAGCLOCK
;
527 pm
->rwdata
= value
; /* divider value */
528 int rc
= vdebug_wait_server(hsock
, pm
);
530 LOG_ERROR("0x%x setting jtag_clock", rc
);
534 LOG_DEBUG("setting jtag clock divider to %" PRIx32
, value
);
539 static int vdebug_jtag_shift_tap(int hsock
, struct vd_shm
*pm
, uint8_t num_pre
,
540 const uint8_t tms_pre
, uint32_t num
, const uint8_t *tdi
,
541 uint8_t num_post
, const uint8_t tms_post
, uint8_t *tdo
,
544 const uint32_t tobits
= 8;
545 uint16_t bytes
, hwords
, anum
, words
, waddr
;
548 pm
->cmd
= VD_CMD_JTAGSHTAP
;
549 vdc
.trans_last
= f_last
|| (vdc
.trans_batch
== VD_BATCH_NO
) || tdo
;
551 waddr
= 0; /* reset buffer offset */
553 waddr
= pm
->offseth
; /* continue from the previous transaction */
554 if (num_post
) /* actual number of bits to shift */
555 anum
= num
+ num_pre
+ num_post
- 1;
557 anum
= num
+ num_pre
;
558 hwords
= (anum
+ 4 * vdc
.buf_width
- 1) / (4 * vdc
.buf_width
); /* in 4B TDI/TMS words */
559 words
= (hwords
+ 1) / 2; /* in 8B TDO words to read */
560 bytes
= (num
+ 7) / 8; /* data only portion in bytes */
561 /* buffer overflow check and flush */
562 if (4 * waddr
+ sizeof(struct vd_jtag_hdr
) + 8 * hwords
+ 64 > VD_BUFFER_LEN
) {
563 vdc
.trans_last
= 1; /* force flush within 64B of buffer end */
564 } else if (4 * waddr
+ sizeof(struct vd_jtag_hdr
) + 8 * hwords
> VD_BUFFER_LEN
) {
565 /* this req does not fit, discard it */
566 LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift",
567 pm
->wid
, anum
, (vdc
.trans_first
<< 14) | (vdc
.trans_last
<< 15), waddr
);
573 struct vd_jtag_hdr
*hdr
= (struct vd_jtag_hdr
*)&pm
->wd8
[4 * waddr
]; /* 8 bytes header */
574 hdr
->cmd
= (tdo
? 3 : 1); /* R and W bits */
576 hdr
->post
= num_post
;
580 pm
->wid
++; /* transaction ID */
581 waddr
+= 2; /* waddr past header */
582 /* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */
583 pm
->wd8
[4 * waddr
] = (tdi
? (tdi
[0] << num_pre
) : 0);
584 pm
->wd8
[4 * waddr
+ 4] = tms_pre
; /* init with tms_pre */
585 if (num
+ num_pre
<= 8) /* and tms_post for num <=4 */
586 pm
->wd8
[4 * waddr
+ 4] |= (tms_post
<< (num
+ num_pre
- 1));
587 for (i
= 1, j
= 4 * waddr
; i
< bytes
; i
++) {
588 if (i
== bytes
- 1 && num
+ num_pre
<= bytes
* tobits
)
589 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8);
591 pm
->wd8
[j
+ i
+ 4] = 0x0;/* placing 4 bytes of TMS bits into high word */
592 if (!tdi
) /* placing 4 bytes of TDI bits into low word */
593 pm
->wd8
[j
+ i
] = 0x0;
595 pm
->wd8
[j
+ i
] = (tdi
[i
] << num_pre
) | (tdi
[i
- 1] >> (8 - num_pre
));
601 if (num
+ num_pre
> bytes
* tobits
) /* in case 1 additional byte needed for TDI */
602 pm
->wd8
[j
+ i
] = (tdi
[i
- 1] >> (8 - num_pre
)); /* put last TDI bits there */
604 if (num
+ num_pre
<= bytes
* tobits
) { /* in case no or 1 additional byte needed */
605 pm
->wd8
[j
+ i
+ 4] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* may need to add higher part */
606 /* in case exactly 1 additional byte needed */
607 } else if (num
+ num_pre
> bytes
* tobits
&& anum
<= (bytes
+ 1) * tobits
) {
608 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8); /* add whole tms_post */
609 } else { /* in case 2 additional bytes, tms_post split */
610 pm
->wd8
[j
+ i
+ 4] = tms_post
<< ((num
+ num_pre
- 1) % 8);/* add lower part of tms_post */
611 if (i
% 4 == 3) /* next byte is in the next 32b word */
612 pm
->wd8
[j
+ i
+ 4 + 5] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* and higher part */
613 else /* next byte is in the same 32b word */
614 pm
->wd8
[j
+ i
+ 4 + 1] = tms_post
>> (8 - (num
+ num_pre
- 1) % 8); /* and higher part */
618 pm
->rwords
+= words
; /* keep track of the words to read */
621 pm
->wwords
= waddr
/ 2 + hwords
; /* payload size *2 to include both TDI and TMS data */
625 if (!waddr
) /* flush issued, but buffer empty */
627 else if (!vdc
.trans_last
) /* buffered request */
628 pm
->offseth
= waddr
+ hwords
* 2; /* offset for next transaction, must be even */
629 else /* execute batch of requests */
630 rc
= vdebug_run_jtag_queue(hsock
, pm
, pm
->waddr
);
631 vdc
.trans_first
= vdc
.trans_last
; /* flush forces trans_first flag */
636 static int vdebug_mem_open(int hsock
, struct vd_shm
*pm
, const char *path
, uint8_t ndx
)
643 pm
->cmd
= VD_CMD_MEMOPEN
;
644 pm
->wbytes
= strlen(path
) + 1; /* includes terminating 0 */
648 memcpy(pm
->wd8
, path
, pm
->wbytes
);
649 rc
= vdebug_wait_server(hsock
, pm
);
651 LOG_ERROR("0x%x opening memory %s", rc
, path
);
652 } else if (ndx
!= pm
->rd16
[1]) {
653 LOG_WARNING("Invalid memory index %" PRIu16
" returned. Direct memory access disabled", pm
->rd16
[1]);
655 vdc
.mem_width
[ndx
] = pm
->rd16
[0] / 8; /* memory width in bytes */
656 vdc
.mem_depth
[ndx
] = pm
->rd32
[1]; /* memory depth in words */
657 LOG_DEBUG("%" PRIx8
": %s memory %" PRIu32
"x%" PRIu32
"B, buffer %" PRIu32
"x%" PRIu32
"B", ndx
, path
,
658 vdc
.mem_depth
[ndx
], vdc
.mem_width
[ndx
], VD_BUFFER_LEN
/ vdc
.mem_width
[ndx
], vdc
.mem_width
[ndx
]);
664 static void vdebug_mem_close(int hsock
, struct vd_shm
*pm
, uint8_t ndx
)
666 pm
->cmd
= VD_CMD_MEMCLOSE
;
667 pm
->rwdata
= ndx
; /* which memory */
672 vdebug_wait_server(hsock
, pm
);
673 LOG_DEBUG("%" PRIx8
": %s", ndx
, vdc
.mem_path
[ndx
]);
676 static int vdebug_init(void)
678 vdc
.hsocket
= vdebug_socket_open(vdc
.server_name
, vdc
.server_port
);
679 pbuf
= calloc(1, sizeof(struct vd_shm
));
681 close_socket(vdc
.hsocket
);
683 LOG_ERROR("cannot allocate %lu bytes", sizeof(struct vd_shm
));
686 if (vdc
.hsocket
<= 0) {
689 LOG_ERROR("cannot connect to vdebug server %s:%" PRIu16
,
690 vdc
.server_name
, vdc
.server_port
);
694 vdc
.poll_cycles
= vdc
.poll_max
;
695 uint32_t sig_mask
= VD_SIG_RESET
| VD_SIG_TRST
| VD_SIG_TCKDIV
;
696 int rc
= vdebug_open(vdc
.hsocket
, pbuf
, vdc
.bfm_path
, vdc
.bfm_type
, vdc
.bfm_period
, sig_mask
);
698 LOG_ERROR("cannot connect to %s, rc 0x%x", vdc
.bfm_path
, rc
);
699 close_socket(vdc
.hsocket
);
704 for (uint8_t i
= 0; i
< vdc
.mem_ndx
; i
++) {
705 rc
= vdebug_mem_open(vdc
.hsocket
, pbuf
, vdc
.mem_path
[i
], i
);
707 LOG_ERROR("cannot connect to %s, rc 0x%x", vdc
.mem_path
[i
], rc
);
710 LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16
,
711 VD_VERSION
, vdc
.bfm_path
, vdc
.server_name
, vdc
.server_port
);
717 static int vdebug_quit(void)
719 for (uint8_t i
= 0; i
< vdc
.mem_ndx
; i
++)
720 if (vdc
.mem_width
[i
])
721 vdebug_mem_close(vdc
.hsocket
, pbuf
, i
);
722 int rc
= vdebug_close(vdc
.hsocket
, pbuf
, vdc
.bfm_type
);
723 LOG_INFO("vdebug %d disconnected from %s through %s:%" PRIu16
" rc:%d", VD_VERSION
,
724 vdc
.bfm_path
, vdc
.server_name
, vdc
.server_port
, rc
);
726 close_socket(vdc
.hsocket
);
733 static int vdebug_reset(int trst
, int srst
)
735 uint16_t sig_val
= 0xffff;
736 uint16_t sig_mask
= 0;
738 sig_mask
|= VD_SIG_RESET
;
740 sig_val
&= ~VD_SIG_RESET
;/* active low */
741 if (transport_is_jtag()) {
742 sig_mask
|= VD_SIG_TRST
;
744 sig_val
&= ~VD_SIG_TRST
; /* active low */
747 LOG_INFO("rst trst:%d srst:%d mask:%" PRIx16
" val:%" PRIx16
, trst
, srst
, sig_mask
, sig_val
);
748 int rc
= vdebug_sig_set(vdc
.hsocket
, pbuf
, sig_mask
, sig_val
);
750 rc
= vdebug_wait(vdc
.hsocket
, pbuf
, 20); /* 20 clock cycles pulse */
755 static int vdebug_jtag_tms_seq(const uint8_t *tms
, int num
, uint8_t f_flush
)
757 LOG_INFO("tms len:%d tms:%x", num
, *(const uint32_t *)tms
);
759 return vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num
, *tms
, 0, NULL
, 0, 0, NULL
, f_flush
);
762 static int vdebug_jtag_path_move(struct pathmove_command
*cmd
, uint8_t f_flush
)
764 uint8_t tms
[DIV_ROUND_UP(cmd
->num_states
, 8)];
765 LOG_INFO("path num states %d", cmd
->num_states
);
767 memset(tms
, 0, DIV_ROUND_UP(cmd
->num_states
, 8));
769 for (uint8_t i
= 0; i
< cmd
->num_states
; i
++) {
770 if (tap_state_transition(tap_get_state(), true) == cmd
->path
[i
])
771 buf_set_u32(tms
, i
, 1, 1);
772 tap_set_state(cmd
->path
[i
]);
775 return vdebug_jtag_tms_seq(tms
, cmd
->num_states
, f_flush
);
778 static int vdebug_jtag_tlr(tap_state_t state
, uint8_t f_flush
)
782 uint8_t cur
= tap_get_state();
783 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
784 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
785 LOG_INFO("tlr from %" PRIx8
" to %" PRIx8
, cur
, state
);
787 rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num_pre
, tms_pre
, 0, NULL
, 0, 0, NULL
, f_flush
);
788 tap_set_state(state
);
794 static int vdebug_jtag_scan(struct scan_command
*cmd
, uint8_t f_flush
)
798 uint8_t cur
= tap_get_state();
799 uint8_t state
= cmd
->ir_scan
? TAP_IRSHIFT
: TAP_DRSHIFT
;
800 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
801 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
802 uint8_t tms_post
= tap_get_tms_path(state
, cmd
->end_state
);
803 uint8_t num_post
= tap_get_tms_path_len(state
, cmd
->end_state
);
804 int num_bits
= jtag_scan_size(cmd
);
805 LOG_DEBUG("scan len:%d fields:%d ir/!dr:%d state cur:%x end:%x",
806 num_bits
, cmd
->num_fields
, cmd
->ir_scan
, cur
, cmd
->end_state
);
807 for (int i
= 0; i
< cmd
->num_fields
; i
++) {
808 uint8_t cur_num_pre
= i
== 0 ? num_pre
: 0;
809 uint8_t cur_tms_pre
= i
== 0 ? tms_pre
: 0;
810 uint8_t cur_num_post
= i
== cmd
->num_fields
- 1 ? num_post
: 0;
811 uint8_t cur_tms_post
= i
== cmd
->num_fields
- 1 ? tms_post
: 0;
812 uint8_t cur_flush
= i
== cmd
->num_fields
- 1 ? f_flush
: 0;
813 rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, cur_num_pre
, cur_tms_pre
,
814 cmd
->fields
[i
].num_bits
, cmd
->fields
[i
].out_value
, cur_num_post
, cur_tms_post
,
815 cmd
->fields
[i
].in_value
, cur_flush
);
820 if (cur
!= cmd
->end_state
)
821 tap_set_state(cmd
->end_state
);
826 static int vdebug_jtag_runtest(int cycles
, tap_state_t state
, uint8_t f_flush
)
828 uint8_t cur
= tap_get_state();
829 uint8_t tms_pre
= tap_get_tms_path(cur
, state
);
830 uint8_t num_pre
= tap_get_tms_path_len(cur
, state
);
831 LOG_DEBUG("idle len:%d state cur:%x end:%x", cycles
, cur
, state
);
832 int rc
= vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, num_pre
, tms_pre
, cycles
, NULL
, 0, 0, NULL
, f_flush
);
834 tap_set_state(state
);
839 static int vdebug_jtag_stableclocks(int num
, uint8_t f_flush
)
841 LOG_INFO("stab len:%d state cur:%x", num
, tap_get_state());
843 return vdebug_jtag_shift_tap(vdc
.hsocket
, pbuf
, 0, 0, num
, NULL
, 0, 0, NULL
, f_flush
);
846 static int vdebug_sleep(int us
)
848 LOG_INFO("sleep %d us", us
);
850 return vdebug_wait(vdc
.hsocket
, pbuf
, us
/ 1000);
853 static int vdebug_jtag_speed(int speed
)
855 unsigned int clkmax
= VD_SCALE_PSTOMS
/ (vdc
.bfm_period
* 2); /* kHz */
856 unsigned int divval
= clkmax
/ speed
;
857 LOG_INFO("jclk speed:%d kHz set, BFM divider %u", speed
, divval
);
859 return vdebug_jtag_clock(vdc
.hsocket
, pbuf
, divval
);
862 static int vdebug_jtag_khz(int khz
, int *jtag_speed
)
864 unsigned int clkmax
= VD_SCALE_PSTOMS
/ (vdc
.bfm_period
* 2); /* kHz */
865 unsigned int divval
= khz
? clkmax
/ khz
: 1;
866 *jtag_speed
= clkmax
/ divval
;
867 LOG_DEBUG("khz speed:%d from khz:%d", *jtag_speed
, khz
);
872 static int vdebug_jtag_div(int speed
, int *khz
)
875 LOG_DEBUG("div khz:%d from speed:%d", *khz
, speed
);
880 static int vdebug_jtag_execute_queue(void)
884 for (struct jtag_command
*cmd
= jtag_command_queue
; rc
== ERROR_OK
&& cmd
; cmd
= cmd
->next
) {
887 rc
= vdebug_jtag_runtest(cmd
->cmd
.runtest
->num_cycles
, cmd
->cmd
.runtest
->end_state
, !cmd
->next
);
889 case JTAG_STABLECLOCKS
:
890 rc
= vdebug_jtag_stableclocks(cmd
->cmd
.stableclocks
->num_cycles
, !cmd
->next
);
893 rc
= vdebug_jtag_tlr(cmd
->cmd
.statemove
->end_state
, !cmd
->next
);
896 rc
= vdebug_jtag_path_move(cmd
->cmd
.pathmove
, !cmd
->next
);
899 rc
= vdebug_jtag_tms_seq(cmd
->cmd
.tms
->bits
, cmd
->cmd
.tms
->num_bits
, !cmd
->next
);
902 rc
= vdebug_sleep(cmd
->cmd
.sleep
->us
);
905 rc
= vdebug_jtag_scan(cmd
->cmd
.scan
, !cmd
->next
);
908 LOG_ERROR("Unknown JTAG command type 0x%x encountered", cmd
->type
);
916 COMMAND_HANDLER(vdebug_set_server
)
918 if ((CMD_ARGC
!= 1) || !strchr(CMD_ARGV
[0], ':'))
919 return ERROR_COMMAND_SYNTAX_ERROR
;
921 char *pchar
= strchr(CMD_ARGV
[0], ':');
923 strncpy(vdc
.server_name
, CMD_ARGV
[0], sizeof(vdc
.server_name
) - 1);
924 int port
= atoi(++pchar
);
925 if (port
< 0 || port
> UINT16_MAX
) {
926 LOG_ERROR("invalid port number %d specified", port
);
927 return ERROR_COMMAND_SYNTAX_ERROR
;
929 vdc
.server_port
= port
;
930 LOG_DEBUG("server: %s port %u", vdc
.server_name
, vdc
.server_port
);
935 COMMAND_HANDLER(vdebug_set_bfm
)
939 if ((CMD_ARGC
!= 2) || (sscanf(CMD_ARGV
[1], "%u%c", &vdc
.bfm_period
, &prefix
) != 2))
940 return ERROR_COMMAND_SYNTAX_ERROR
;
942 strncpy(vdc
.bfm_path
, CMD_ARGV
[0], sizeof(vdc
.bfm_path
) - 1);
945 vdc
.bfm_period
*= 1000000;
948 vdc
.bfm_period
*= 1000;
954 vdc
.bfm_type
= VD_BFM_JTAG
;
955 LOG_DEBUG("bfm_path: %s clk_period %ups", vdc
.bfm_path
, vdc
.bfm_period
);
960 COMMAND_HANDLER(vdebug_set_mem
)
963 return ERROR_COMMAND_SYNTAX_ERROR
;
965 if (vdc
.mem_ndx
>= VD_MAX_MEMORIES
) {
966 LOG_ERROR("mem_path declared more than %d allowed times", VD_MAX_MEMORIES
);
970 strncpy(vdc
.mem_path
[vdc
.mem_ndx
], CMD_ARGV
[0], sizeof(vdc
.mem_path
[vdc
.mem_ndx
]) - 1);
971 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], vdc
.mem_base
[vdc
.mem_ndx
]);
972 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], vdc
.mem_size
[vdc
.mem_ndx
]);
973 LOG_DEBUG("mem_path: set %s @ 0x%08x+0x%08x", vdc
.mem_path
[vdc
.mem_ndx
],
974 vdc
.mem_base
[vdc
.mem_ndx
], vdc
.mem_size
[vdc
.mem_ndx
]);
980 COMMAND_HANDLER(vdebug_set_batching
)
983 return ERROR_COMMAND_SYNTAX_ERROR
;
985 if (isdigit((unsigned char)CMD_ARGV
[0][0]))
986 vdc
.trans_batch
= (CMD_ARGV
[0][0] == '0' ? 0 : (CMD_ARGV
[0][0] == '1' ? 1 : 2));
987 else if (CMD_ARGV
[0][0] == 'r')
988 vdc
.trans_batch
= VD_BATCH_WR
;
989 else if (CMD_ARGV
[0][0] == 'w')
990 vdc
.trans_batch
= VD_BATCH_WO
;
992 vdc
.trans_batch
= VD_BATCH_NO
;
993 LOG_DEBUG("batching: set to %u", vdc
.trans_batch
);
998 COMMAND_HANDLER(vdebug_set_polling
)
1001 return ERROR_COMMAND_SYNTAX_ERROR
;
1003 vdc
.poll_min
= atoi(CMD_ARGV
[0]);
1004 vdc
.poll_max
= atoi(CMD_ARGV
[1]);
1005 LOG_DEBUG("polling: set min %u max %u", vdc
.poll_min
, vdc
.poll_max
);
1010 static const struct command_registration vdebug_command_handlers
[] = {
1013 .handler
= &vdebug_set_server
,
1014 .mode
= COMMAND_CONFIG
,
1015 .help
= "set the vdebug server name or address",
1016 .usage
= "<host:port>",
1020 .handler
= &vdebug_set_bfm
,
1021 .mode
= COMMAND_CONFIG
,
1022 .help
= "set the vdebug BFM hierarchical path",
1023 .usage
= "<path> <clk_period[p|n|u]s>",
1027 .handler
= &vdebug_set_mem
,
1028 .mode
= COMMAND_ANY
,
1029 .help
= "set the design memory for the code load",
1030 .usage
= "<path> <base_address> <size>",
1034 .handler
= &vdebug_set_batching
,
1035 .mode
= COMMAND_CONFIG
,
1036 .help
= "set the transaction batching no|wr|rd [0|1|2]",
1041 .handler
= &vdebug_set_polling
,
1042 .mode
= COMMAND_CONFIG
,
1043 .help
= "set the polling pause, executing hardware cycles between min and max",
1044 .usage
= "<min cycles> <max cycles>",
1046 COMMAND_REGISTRATION_DONE
1049 static const struct command_registration vdebug_command
[] = {
1052 .chain
= vdebug_command_handlers
,
1053 .mode
= COMMAND_ANY
,
1054 .help
= "vdebug command group",
1057 COMMAND_REGISTRATION_DONE
1060 static struct jtag_interface vdebug_jtag_ops
= {
1061 .supported
= DEBUG_CAP_TMS_SEQ
,
1062 .execute_queue
= vdebug_jtag_execute_queue
,
1065 struct adapter_driver vdebug_adapter_driver
= {
1067 .transports
= jtag_only
,
1068 .speed
= vdebug_jtag_speed
,
1069 .khz
= vdebug_jtag_khz
,
1070 .speed_div
= vdebug_jtag_div
,
1071 .commands
= vdebug_command
,
1072 .init
= vdebug_init
,
1073 .quit
= vdebug_quit
,
1074 .reset
= vdebug_reset
,
1075 .jtag_ops
= &vdebug_jtag_ops
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)