From f97915f248d7e3e7db49139b4fbb40e1e480ed53 Mon Sep 17 00:00:00 2001 From: Jacek Wuwer Date: Wed, 4 May 2022 10:15:57 +0200 Subject: [PATCH] drivers/vdebug: add support for DAP level interface This patch adds support for DAP interface to Cadence vdebug driver. It implements a new transport layer for dapdirect_swd. Change-Id: I64b02a9e1ce91e552e07fca692879655496f88b6 Signed-off-by: Jacek Wuwer Reviewed-on: https://review.openocd.org/c/openocd/+/6965 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 4 +- src/jtag/drivers/vdebug.c | 534 +++++++++++++++++++++++-------- tcl/board/vd_a53x2_dap.cfg | 29 ++ tcl/board/vd_a53x2_jtag.cfg | 2 +- tcl/board/vd_m4_dap.cfg | 26 ++ tcl/board/vd_m4_jtag.cfg | 2 +- tcl/board/vd_m7_jtag.cfg | 30 ++ tcl/board/vd_pulpissimo_jtag.cfg | 2 +- tcl/board/vd_swerv_jtag.cfg | 2 +- tcl/target/vd_riscv.cfg | 3 +- 10 files changed, 488 insertions(+), 146 deletions(-) create mode 100644 tcl/board/vd_a53x2_dap.cfg create mode 100644 tcl/board/vd_m4_dap.cfg create mode 100644 tcl/board/vd_m7_jtag.cfg diff --git a/doc/openocd.texi b/doc/openocd.texi index b213798c31..03bb508479 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -594,8 +594,8 @@ produced, PDF schematics are easily found and it is easy to make. @item @b{vdebug} @* A driver for Cadence virtual Debug Interface to emulated or simulated targets. It implements a client connecting to the vdebug server, which in turn communicates -with the emulated or simulated RTL model through a transactor. The current version -supports only JTAG as a transport, but other virtual transports, like DAP are planned. +with the emulated or simulated RTL model through a transactor. The driver supports +JTAG and DAP-level transports. @item @b{jtag_dpi} @* A JTAG driver acting as a client for the SystemVerilog Direct Programming diff --git a/src/jtag/drivers/vdebug.c b/src/jtag/drivers/vdebug.c index a81740cb18..035c1bee26 100644 --- a/src/jtag/drivers/vdebug.c +++ b/src/jtag/drivers/vdebug.c @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ /*---------------------------------------------------------------------------- - * Copyright 2020-2021 Cadence Design Systems, Inc. + * Copyright 2020-2022 Cadence Design Systems, Inc. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -27,9 +27,9 @@ * @file * * @brief the virtual debug interface provides a connection between a sw debugger - * and the simulated, emulated core over a soft connection, implemented by DPI - * The vdebug debug driver currently supports JTAG transport - * TODO: implement support and test big endian platforms + * and the simulated, emulated core. The openOCD client connects via TCP sockets + * with vdebug server and over DPI-based transactor with the emulation or simulation + * The vdebug debug driver supports JTAG and DAP-level transports * */ @@ -68,16 +68,18 @@ #include "jtag/interface.h" #include "jtag/commands.h" #include "transport/transport.h" +#include "target/arm_adi_v5.h" #include "helper/time_support.h" #include "helper/replacements.h" #include "helper/log.h" +#include "helper/list.h" -#define VD_VERSION 43 +#define VD_VERSION 44 #define VD_BUFFER_LEN 4024 #define VD_CHEADER_LEN 24 #define VD_SHEADER_LEN 16 -#define VD_MAX_MEMORIES 4 +#define VD_MAX_MEMORIES 20 #define VD_POLL_INTERVAL 500 #define VD_SCALE_PSTOMS 1000000000 @@ -149,12 +151,21 @@ enum { VD_CMD_SIGSET = 0x0a, VD_CMD_SIGGET = 0x0b, VD_CMD_JTAGCLOCK = 0x0f, + VD_CMD_REGWRITE = 0x15, + VD_CMD_REGREAD = 0x16, VD_CMD_JTAGSHTAP = 0x1a, VD_CMD_MEMOPEN = 0x21, VD_CMD_MEMCLOSE = 0x22, VD_CMD_MEMWRITE = 0x23, }; +enum { + VD_ASPACE_AP = 0x01, + VD_ASPACE_DP = 0x02, + VD_ASPACE_ID = 0x03, + VD_ASPACE_AB = 0x04, +}; + enum { VD_BATCH_NO = 0, VD_BATCH_WO = 1, @@ -165,37 +176,32 @@ struct vd_shm { struct { /* VD_CHEADER_LEN written by client */ uint8_t cmd; /* 000; command */ uint8_t type; /* 001; interface type */ - uint16_t waddr; /* 002; write pointer */ - uint16_t wbytes; /* 004; data bytes */ - uint16_t rbytes; /* 006; data bytes to read */ - uint16_t wwords; /* 008; data words */ - uint16_t rwords; /* 00a; data words to read */ - uint32_t rwdata; /* 00c; read/write data */ - uint32_t offset; /* 010; address offset */ - uint16_t offseth; /* 014; address offset 47:32 */ - uint16_t wid; /* 016; request id*/ - }; - union { /* 018; */ - uint8_t wd8[VD_BUFFER_LEN]; - uint16_t wd16[VD_BUFFER_LEN / 2]; - uint32_t wd32[VD_BUFFER_LEN / 4]; - uint64_t wd64[VD_BUFFER_LEN / 8]; + uint8_t waddr[2]; /* 002; write pointer */ + uint8_t wbytes[2]; /* 004; data bytes */ + uint8_t rbytes[2]; /* 006; data bytes to read */ + uint8_t wwords[2]; /* 008; data words */ + uint8_t rwords[2]; /* 00a; data words to read */ + uint8_t rwdata[4]; /* 00c; read/write data */ + uint8_t offset[4]; /* 010; address offset */ + uint8_t offseth[2]; /* 014; address offset 47:32 */ + uint8_t wid[2]; /* 016; request id*/ }; + uint8_t wd8[VD_BUFFER_LEN]; /* 018; */ struct { /* VD_SHEADER_LEN written by server */ - uint16_t rid; /* fd0: request id read */ - uint16_t awords; /* fd2: actual data words read back */ - int32_t status; /* fd4; */ - uint64_t duttime; /* fd8; */ + uint8_t rid[2]; /* fd0: request id read */ + uint8_t awords[2]; /* fd2: actual data words read back */ + uint8_t status[4]; /* fd4; */ + uint8_t duttime[8]; /* fd8; */ }; - union { /* fe0: */ - uint8_t rd8[VD_BUFFER_LEN]; - uint16_t rd16[VD_BUFFER_LEN / 2]; - uint32_t rd32[VD_BUFFER_LEN / 4]; - uint64_t rd64[VD_BUFFER_LEN / 8]; - }; - uint32_t state; /* 1f98; connection state */ - uint32_t count; /* 1f9c; */ + uint8_t rd8[VD_BUFFER_LEN]; /* fe0: */ + uint8_t state[4]; /* 1f98; connection state */ + uint8_t count[4]; /* 1f9c; */ uint8_t dummy[96]; /* 1fa0; 48+40B+8B; */ +} __attribute__((packed)); + +struct vd_rdata { + struct list_head lh; + uint8_t *rdata; }; struct vd_client { @@ -222,7 +228,7 @@ struct vd_client { char server_name[32]; char bfm_path[128]; char mem_path[VD_MAX_MEMORIES][128]; - uint8_t *tdo; + struct vd_rdata rdataq; }; struct vd_jtag_hdr { @@ -234,6 +240,16 @@ struct vd_jtag_hdr { uint64_t rlen:16; }; +struct vd_reg_hdr { + uint64_t prot:3; + uint64_t nonincr:1; + uint64_t haddr:12; + uint64_t tlen:11; + uint64_t asize:3; + uint64_t cmd:2; + uint64_t addr:32; +}; + static struct vd_shm *pbuf; static struct vd_client vdc; @@ -277,7 +293,7 @@ static int vdebug_socket_open(char *server_addr, uint32_t port) LOG_ERROR("socket_open: cannot resolve address %s, error %d", server_addr, vdebug_socket_error()); rc = VD_ERR_SOC_ADDR; } else { - ((struct sockaddr_in *)(ainfo->ai_addr))->sin_port = htons(port); + buf_set_u32((uint8_t *)ainfo->ai_addr->sa_data, 0, 16, htons(port)); if (connect(hsock, ainfo->ai_addr, sizeof(struct sockaddr)) < 0) { LOG_ERROR("socket_open: cannot connect to %s:%d, error %d", server_addr, port, vdebug_socket_error()); rc = VD_ERR_SOC_CONN; @@ -299,8 +315,8 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem) { int rc; int dreceived = 0; - int offset = (uint8_t *)&pmem->rid - &pmem->cmd; - int to_receive = VD_SHEADER_LEN + pmem->rbytes; + int offset = &pmem->rid[0] - &pmem->cmd; + int to_receive = VD_SHEADER_LEN + le_to_h_u16(pmem->rbytes); char *pb = (char *)pmem; do { @@ -320,7 +336,7 @@ static int vdebug_socket_receive(int hsock, struct vd_shm *pmem) static int vdebug_socket_send(int hsock, struct vd_shm *pmem) { - int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + pmem->wbytes, 0); + int rc = send(hsock, (const char *)&pmem->cmd, VD_CHEADER_LEN + le_to_h_u16(pmem->wbytes), 0); if (rc <= 0) LOG_WARNING("socket_send: send failed, error %d", vdebug_socket_error()); else @@ -333,6 +349,7 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem) { if (!hsock) return VD_ERR_SOC_OPEN; + int st = vdebug_socket_send(hsock, pmem); if (st <= 0) return VD_ERR_SOC_SEND; @@ -341,9 +358,9 @@ static uint32_t vdebug_wait_server(int hsock, struct vd_shm *pmem) if (rd <= 0) return VD_ERR_SOC_RECV; - int rc = pmem->status; + int rc = le_to_h_u32(pmem->status); LOG_DEBUG_IO("wait_server: cmd %02" PRIx8 " done, sent %d, rcvd %d, status %d", - pmem->cmd, st, rd, rc); + pmem->cmd, st, rd, rc); return rc; } @@ -356,22 +373,23 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) int64_t ts, te; uint8_t *tdo; int rc; - struct vd_jtag_hdr *hdr; + uint64_t jhdr; + struct vd_rdata *rd; req = 0; /* beginning of request */ waddr = 0; rwords = 0; - pm->wbytes = pm->wwords * vdc.buf_width; - pm->rbytes = pm->rwords * vdc.buf_width; + h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width); + h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width); ts = timeval_ms(); rc = vdebug_wait_server(hsock, pm); while (!rc && (req < count)) { /* loop over requests to read data and print out */ - hdr = (struct vd_jtag_hdr *)&pm->wd8[waddr * 4]; - hwords = hdr->wlen; - words = hdr->rlen; - anum = hdr->tlen; - num_pre = hdr->pre; - num_post = hdr->post; + jhdr = le_to_h_u64(&pm->wd8[waddr * 4]); + words = jhdr >> 48; + hwords = (jhdr >> 32) & 0xffff; + anum = jhdr & 0xffffff; + num_pre = (jhdr >> 27) & 0x7; + num_post = (jhdr >> 24) & 0x7; if (num_post) num = anum - num_pre - num_post + 1; else @@ -379,21 +397,29 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) bytes = (num + 7) / 8; vdc.trans_last = (req + 1) < count ? 0 : 1; vdc.trans_first = waddr ? 0 : 1; - if (hdr->cmd == 3) { /* read */ - tdo = vdc.tdo; + if (((jhdr >> 30) & 0x3) == 3) { /* cmd is read */ + if (!rwords) { + rd = &vdc.rdataq; + tdo = rd->rdata; + } else { + rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh); + tdo = rd->rdata; + list_del(&rd->lh); + free(rd); + } for (unsigned int j = 0; j < bytes; j++) { tdo[j] = (pm->rd8[rwords * 8 + j] >> num_pre) | (pm->rd8[rwords * 8 + j + 1] << (8 - num_pre)); - LOG_DEBUG_IO("%04x D0[%02x]:%02x", pm->wid - count + req, j, tdo[j]); + LOG_DEBUG_IO("%04x D0[%02x]:%02x", le_to_h_u16(pm->wid) - count + req, j, tdo[j]); } rwords += words; /* read data offset */ } else { tdo = NULL; } - waddr += sizeof(struct vd_jtag_hdr) / 4; /* waddr past header */ + waddr += sizeof(uint64_t) / 4; /* waddr past header */ tdi = (pm->wd8[waddr * 4] >> num_pre) | (pm->wd8[waddr * 4 + 1] << (8 - num_pre)); tms = (pm->wd8[waddr * 4 + 4] >> num_pre) | (pm->wd8[waddr * 4 + 4 + 1] << (8 - num_pre)); - LOG_DEBUG("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x", - pm->wid - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15), + LOG_DEBUG_IO("%04x L:%02d O:%05x @%03x DI:%02x MS:%02x DO:%02x", + le_to_h_u16(pm->wid) - count + req, num, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr - 2, tdi, tms, (tdo ? tdo[0] : 0xdd)); waddr += hwords * 2; /* start of next request */ req += 1; @@ -406,10 +432,83 @@ int vdebug_run_jtag_queue(int hsock, struct vd_shm *pm, unsigned int count) te = timeval_ms(); vdc.targ_time += (uint32_t)(te - ts); - pm->offseth = 0; /* reset buffer write address */ - pm->offset = 0; - pm->rwords = 0; - pm->waddr = 0; + h_u16_to_le(pm->offseth, 0); /* reset buffer write address */ + h_u32_to_le(pm->offset, 0); + h_u16_to_le(pm->rwords, 0); + h_u16_to_le(pm->waddr, 0); + assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */ + + return rc; +} + +int vdebug_run_reg_queue(int hsock, struct vd_shm *pm, unsigned int count) +{ + unsigned int num, awidth, wwidth; + unsigned int req, waddr, rwords; + uint8_t aspace; + uint32_t addr; + int64_t ts, te; + uint8_t *data; + int rc; + uint64_t rhdr; + struct vd_rdata *rd; + + req = 0; /* beginning of request */ + waddr = 0; + rwords = 0; + h_u16_to_le(pm->wbytes, le_to_h_u16(pm->wwords) * vdc.buf_width); + h_u16_to_le(pm->rbytes, le_to_h_u16(pm->rwords) * vdc.buf_width); + ts = timeval_ms(); + rc = vdebug_wait_server(hsock, pm); + while (!rc && (req < count)) { /* loop over requests to read data and print out */ + rhdr = le_to_h_u64(&pm->wd8[waddr * 4]); + addr = rhdr >> 32; /* reconstruct data for a single request */ + num = (rhdr >> 16) & 0x7ff; + aspace = rhdr & 0x3; + awidth = (1 << ((rhdr >> 27) & 0x7)); + wwidth = (awidth + vdc.buf_width - 1) / vdc.buf_width; + vdc.trans_last = (req + 1) < count ? 0 : 1; + vdc.trans_first = waddr ? 0 : 1; + if (((rhdr >> 30) & 0x3) == 2) { /* cmd is read */ + if (num) { + if (!rwords) { + rd = &vdc.rdataq; + data = rd->rdata; + } else { + rd = list_first_entry(&vdc.rdataq.lh, struct vd_rdata, lh); + data = rd->rdata; + list_del(&rd->lh); + free(rd); + } + for (unsigned int j = 0; j < num; j++) + memcpy(&data[j * awidth], &pm->rd8[(rwords + j) * awidth], awidth); + } + LOG_DEBUG_IO("read %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + (num ? le_to_h_u32(&pm->rd8[rwords * 4]) : 0xdead)); + rwords += num * wwidth; + waddr += sizeof(uint64_t) / 4; /* waddr past header */ + } else { + LOG_DEBUG_IO("write %04x AS:%02x RG:%02x O:%05x @%03x D:%08x", le_to_h_u16(pm->wid) - count + req, + aspace, addr, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr, + le_to_h_u32(&pm->wd8[(waddr + num + 1) * 4])); + waddr += sizeof(uint64_t) / 4 + (num * wwidth * awidth + 3) / 4; + } + req += 1; + } + + if (rc) { + LOG_ERROR("0x%x executing transaction", rc); + rc = ERROR_FAIL; + } + + te = timeval_ms(); + vdc.targ_time += (uint32_t)(te - ts); + h_u16_to_le(pm->offseth, 0); /* reset buffer write address */ + h_u32_to_le(pm->offset, 0); + h_u16_to_le(pm->rwords, 0); + h_u16_to_le(pm->waddr, 0); + assert(list_empty(&vdc.rdataq.lh));/* list should be empty after run queue */ return rc; } @@ -420,35 +519,35 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path, int rc = VD_ERR_NOT_OPEN; pm->cmd = VD_CMD_OPEN; - pm->wid = VD_VERSION; /* client version */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wid, VD_VERSION); /* client version */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); rc = vdebug_wait_server(hsock, pm); if (rc != 0) { /* communication problem */ LOG_ERROR("0x%x connecting to server", rc); - } else if (pm->rid < pm->wid) { - LOG_ERROR("server version %d too old for the client %d", pm->rid, pm->wid); + } else if (le_to_h_u16(pm->rid) < le_to_h_u16(pm->wid)) { + LOG_ERROR("server version %d too old for the client %d", le_to_h_u16(pm->rid), le_to_h_u16(pm->wid)); pm->cmd = VD_CMD_CLOSE; /* let server close the connection */ vdebug_wait_server(hsock, pm); rc = VD_ERR_VERSION; } else { pm->cmd = VD_CMD_CONNECT; pm->type = type; /* BFM type to connect to, here JTAG */ - pm->rwdata = sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16); - pm->wbytes = strlen(path) + 1; - pm->rbytes = 12; - pm->wid = 0; /* reset wid for transaction ID */ - pm->wwords = 0; - pm->rwords = 0; - memcpy(pm->wd8, path, pm->wbytes + 1); + h_u32_to_le(pm->rwdata, sig_mask | VD_SIG_BUF | (VD_SIG_BUF << 16)); + h_u16_to_le(pm->wbytes, strlen(path) + 1); + h_u16_to_le(pm->rbytes, 12); + h_u16_to_le(pm->wid, 0); /* reset wid for transaction ID */ + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); + memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes)); rc = vdebug_wait_server(hsock, pm); - vdc.sig_read = pm->rwdata >> 16; /* signal read mask */ - vdc.sig_write = pm->rwdata; /* signal write mask */ + vdc.sig_read = le_to_h_u32(pm->rwdata) >> 16; /* signal read mask */ + vdc.sig_write = le_to_h_u32(pm->rwdata); /* signal write mask */ vdc.bfm_period = period_ps; - vdc.buf_width = pm->rd32[0] / 8;/* access width in bytes */ - vdc.addr_bits = pm->rd32[2]; /* supported address bits */ + vdc.buf_width = le_to_h_u32(&pm->rd8[0]) / 8;/* access width in bytes */ + vdc.addr_bits = le_to_h_u32(&pm->rd8[2 * 4]); /* supported address bits */ } if (rc) { @@ -456,6 +555,7 @@ static int vdebug_open(int hsock, struct vd_shm *pm, const char *path, return ERROR_FAIL; } + INIT_LIST_HEAD(&vdc.rdataq.lh); LOG_DEBUG("%s type %0x, period %dps, buffer %dx%dB signals r%04xw%04x", path, type, vdc.bfm_period, VD_BUFFER_LEN / vdc.buf_width, vdc.buf_width, vdc.sig_read, vdc.sig_write); @@ -467,17 +567,17 @@ static int vdebug_close(int hsock, struct vd_shm *pm, uint8_t type) { pm->cmd = VD_CMD_DISCONNECT; pm->type = type; /* BFM type, here JTAG */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); pm->cmd = VD_CMD_CLOSE; - pm->wid = VD_VERSION; /* client version */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u16_to_le(pm->wid, VD_VERSION); /* client version */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); LOG_DEBUG("type %0x", type); @@ -488,9 +588,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles) { if (cycles) { pm->cmd = VD_CMD_WAIT; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = cycles; /* clock sycles to wait */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, cycles); /* clock sycles to wait */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x waiting %" PRIx32 " cycles", rc, cycles); @@ -505,9 +605,9 @@ static int vdebug_wait(int hsock, struct vd_shm *pm, uint32_t cycles) static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uint32_t value) { pm->cmd = VD_CMD_SIGSET; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = (write_mask << 16) | (value & 0xffff); /* mask and value of signals to set */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, (write_mask << 16) | (value & 0xffff)); /* mask and value of signals to set */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x setting signals %04" PRIx32, rc, write_mask); @@ -522,9 +622,9 @@ static int vdebug_sig_set(int hsock, struct vd_shm *pm, uint32_t write_mask, uin static int vdebug_jtag_clock(int hsock, struct vd_shm *pm, uint32_t value) { pm->cmd = VD_CMD_JTAGCLOCK; - pm->wbytes = 0; - pm->rbytes = 0; - pm->rwdata = value; /* divider value */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u32_to_le(pm->rwdata, value); /* divider value */ int rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x setting jtag_clock", rc); @@ -546,11 +646,11 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, int rc = 0; pm->cmd = VD_CMD_JTAGSHTAP; - vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO) || tdo; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); if (vdc.trans_first) waddr = 0; /* reset buffer offset */ else - waddr = pm->offseth; /* continue from the previous transaction */ + waddr = le_to_h_u32(pm->offseth); /* continue from the previous transaction */ if (num_post) /* actual number of bits to shift */ anum = num + num_pre + num_post - 1; else @@ -559,25 +659,22 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, words = (hwords + 1) / 2; /* in 8B TDO words to read */ bytes = (num + 7) / 8; /* data only portion in bytes */ /* buffer overflow check and flush */ - if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords + 64 > VD_BUFFER_LEN) { + if (4 * waddr + sizeof(uint64_t) + 8 * hwords + 64 > VD_BUFFER_LEN) { vdc.trans_last = 1; /* force flush within 64B of buffer end */ - } else if (4 * waddr + sizeof(struct vd_jtag_hdr) + 8 * hwords > VD_BUFFER_LEN) { + } else if (4 * waddr + sizeof(uint64_t) + 8 * hwords > VD_BUFFER_LEN) { /* this req does not fit, discard it */ LOG_ERROR("%04x L:%02d O:%05x @%04x too many bits to shift", - pm->wid, anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr); + le_to_h_u16(pm->wid), anum, (vdc.trans_first << 14) | (vdc.trans_last << 15), waddr); rc = ERROR_FAIL; } if (!rc && anum) { - uint16_t i, j; - struct vd_jtag_hdr *hdr = (struct vd_jtag_hdr *)&pm->wd8[4 * waddr]; /* 8 bytes header */ - hdr->cmd = (tdo ? 3 : 1); /* R and W bits */ - hdr->pre = num_pre; - hdr->post = num_post; - hdr->tlen = anum; - hdr->wlen = hwords; - hdr->rlen = words; - pm->wid++; /* transaction ID */ + uint16_t i, j; /* portability requires to use bit operations for 8B JTAG header */ + uint64_t jhdr = (tdo ? ((uint64_t)(words) << 48) : 0) + ((uint64_t)(hwords) << 32) + + ((tdo ? 3UL : 1UL) << 30) + (num_pre << 27) + (num_post << 24) + anum; + h_u64_to_le(&pm->wd8[4 * waddr], jhdr); + + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); /* transaction ID */ waddr += 2; /* waddr past header */ /* TDI/TMS data follows as 32 bit word pairs {TMS,TDI} */ pm->wd8[4 * waddr] = (tdi ? (tdi[0] << num_pre) : 0); @@ -615,19 +712,102 @@ static int vdebug_jtag_shift_tap(int hsock, struct vd_shm *pm, uint8_t num_pre, } if (tdo) { - pm->rwords += words; /* keep track of the words to read */ - vdc.tdo = tdo; + struct vd_rdata *rd; + if (le_to_h_u16(pm->rwords) == 0) { + rd = &vdc.rdataq; + } else { + rd = calloc(1, sizeof(struct vd_rdata)); + if (!rd) /* check allocation for 24B */ + return ERROR_FAIL; + list_add_tail(&rd->lh, &vdc.rdataq.lh); + } + rd->rdata = tdo; + h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + words);/* keep track of the words to read */ } - pm->wwords = waddr / 2 + hwords; /* payload size *2 to include both TDI and TMS data */ - pm->waddr++; + h_u16_to_le(pm->wwords, waddr / 2 + hwords); /* payload size *2 to include both TDI and TMS data */ + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); } if (!waddr) /* flush issued, but buffer empty */ ; else if (!vdc.trans_last) /* buffered request */ - pm->offseth = waddr + hwords * 2; /* offset for next transaction, must be even */ + h_u16_to_le(pm->offseth, waddr + hwords * 2); /* offset for next transaction, must be even */ else /* execute batch of requests */ - rc = vdebug_run_jtag_queue(hsock, pm, pm->waddr); + rc = vdebug_run_jtag_queue(hsock, pm, le_to_h_u16(pm->waddr)); + vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ + + return rc; +} + +static int vdebug_reg_write(int hsock, struct vd_shm *pm, const uint32_t reg, + const uint32_t data, uint8_t aspace, uint8_t f_last) +{ + uint32_t waddr; + int rc = ERROR_OK; + + pm->cmd = VD_CMD_REGWRITE; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); + if (vdc.trans_first) + waddr = 0; /* reset buffer offset */ + else + waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */ + + if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN) + vdc.trans_last = 1; /* force flush, no room for next request */ + + uint64_t rhdr = ((uint64_t)reg << 32) + (1UL << 30) + (2UL << 27) + (1UL << 16) + aspace; + h_u64_to_le(&pm->wd8[4 * waddr], rhdr); + h_u32_to_le(&pm->wd8[4 * (waddr + 2)], data); + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); + h_u16_to_le(pm->wwords, waddr + 3); + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); + if (!vdc.trans_last) /* buffered request */ + h_u16_to_le(pm->offseth, waddr + 3); + else + rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr)); + vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ + + return rc; +} + +static int vdebug_reg_read(int hsock, struct vd_shm *pm, const uint32_t reg, + uint32_t *data, uint8_t aspace, uint8_t f_last) +{ + uint32_t waddr; + int rc = ERROR_OK; + + pm->cmd = VD_CMD_REGREAD; + vdc.trans_last = f_last || (vdc.trans_batch == VD_BATCH_NO); + if (vdc.trans_first) + waddr = 0; /* reset buffer offset */ + else + waddr = le_to_h_u16(pm->offseth); /* continue from the previous transaction */ + + if (4 * waddr + 2 * sizeof(uint64_t) + 4 > VD_BUFFER_LEN) + vdc.trans_last = 1; /* force flush, no room for next request */ + + uint64_t rhdr = ((uint64_t)reg << 32) + (2UL << 30) + (2UL << 27) + ((data ? 1UL : 0UL) << 16) + aspace; + h_u64_to_le(&pm->wd8[4 * waddr], rhdr); + h_u16_to_le(pm->wid, le_to_h_u16(pm->wid) + 1); + if (data) { + struct vd_rdata *rd; + if (le_to_h_u16(pm->rwords) == 0) { + rd = &vdc.rdataq; + } else { + rd = calloc(1, sizeof(struct vd_rdata)); + if (!rd) /* check allocation for 24B */ + return ERROR_FAIL; + list_add_tail(&rd->lh, &vdc.rdataq.lh); + } + rd->rdata = (uint8_t *)data; + h_u16_to_le(pm->rwords, le_to_h_u16(pm->rwords) + 1); + } + h_u16_to_le(pm->wwords, waddr + 2); + h_u16_to_le(pm->waddr, le_to_h_u16(pm->waddr) + 1); + if (!vdc.trans_last) /* buffered request */ + h_u16_to_le(pm->offseth, waddr + 2); + else + rc = vdebug_run_reg_queue(hsock, pm, le_to_h_u16(pm->waddr)); vdc.trans_first = vdc.trans_last; /* flush forces trans_first flag */ return rc; @@ -641,19 +821,19 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8 return ERROR_OK; pm->cmd = VD_CMD_MEMOPEN; - pm->wbytes = strlen(path) + 1; /* includes terminating 0 */ - pm->rbytes = 8; - pm->wwords = 0; - pm->rwords = 0; - memcpy(pm->wd8, path, pm->wbytes); + h_u16_to_le(pm->wbytes, strlen(path) + 1); /* includes terminating 0 */ + h_u16_to_le(pm->rbytes, 8); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); + memcpy(pm->wd8, path, le_to_h_u16(pm->wbytes)); rc = vdebug_wait_server(hsock, pm); if (rc) { LOG_ERROR("0x%x opening memory %s", rc, path); - } else if (ndx != pm->rd16[1]) { - LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd16[1]); + } else if (ndx != pm->rd8[2]) { + LOG_WARNING("Invalid memory index %" PRIu16 " returned. Direct memory access disabled", pm->rd8[2]); } else { - vdc.mem_width[ndx] = pm->rd16[0] / 8; /* memory width in bytes */ - vdc.mem_depth[ndx] = pm->rd32[1]; /* memory depth in words */ + vdc.mem_width[ndx] = le_to_h_u16(&pm->rd8[0]) / 8; /* memory width in bytes */ + vdc.mem_depth[ndx] = le_to_h_u32(&pm->rd8[4]); /* memory depth in words */ LOG_DEBUG("%" PRIx8 ": %s memory %" PRIu32 "x%" PRIu32 "B, buffer %" PRIu32 "x%" PRIu32 "B", ndx, path, vdc.mem_depth[ndx], vdc.mem_width[ndx], VD_BUFFER_LEN / vdc.mem_width[ndx], vdc.mem_width[ndx]); } @@ -664,15 +844,16 @@ static int vdebug_mem_open(int hsock, struct vd_shm *pm, const char *path, uint8 static void vdebug_mem_close(int hsock, struct vd_shm *pm, uint8_t ndx) { pm->cmd = VD_CMD_MEMCLOSE; - pm->rwdata = ndx; /* which memory */ - pm->wbytes = 0; - pm->rbytes = 0; - pm->wwords = 0; - pm->rwords = 0; + h_u32_to_le(pm->rwdata, ndx); /* which memory */ + h_u16_to_le(pm->wbytes, 0); + h_u16_to_le(pm->rbytes, 0); + h_u16_to_le(pm->wwords, 0); + h_u16_to_le(pm->rwords, 0); vdebug_wait_server(hsock, pm); LOG_DEBUG("%" PRIx8 ": %s", ndx, vdc.mem_path[ndx]); } + static int vdebug_init(void) { vdc.hsocket = vdebug_socket_open(vdc.server_name, vdc.server_port); @@ -680,7 +861,7 @@ static int vdebug_init(void) if (!pbuf) { close_socket(vdc.hsocket); vdc.hsocket = 0; - LOG_ERROR("cannot allocate %lu bytes", sizeof(struct vd_shm)); + LOG_ERROR("cannot allocate %zu bytes", sizeof(struct vd_shm)); return ERROR_FAIL; } if (vdc.hsocket <= 0) { @@ -692,10 +873,13 @@ static int vdebug_init(void) } vdc.trans_first = 1; vdc.poll_cycles = vdc.poll_max; - uint32_t sig_mask = VD_SIG_RESET | VD_SIG_TRST | VD_SIG_TCKDIV; + uint32_t sig_mask = VD_SIG_RESET; + if (transport_is_jtag()) + sig_mask |= VD_SIG_TRST | VD_SIG_TCKDIV; + int rc = vdebug_open(vdc.hsocket, pbuf, vdc.bfm_path, vdc.bfm_type, vdc.bfm_period, sig_mask); if (rc != 0) { - LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.bfm_path, rc); + LOG_ERROR("0x%x cannot connect to %s", rc, vdc.bfm_path); close_socket(vdc.hsocket); vdc.hsocket = 0; free(pbuf); @@ -704,7 +888,7 @@ static int vdebug_init(void) for (uint8_t i = 0; i < vdc.mem_ndx; i++) { rc = vdebug_mem_open(vdc.hsocket, pbuf, vdc.mem_path[i], i); if (rc != 0) - LOG_ERROR("cannot connect to %s, rc 0x%x", vdc.mem_path[i], rc); + LOG_ERROR("0x%x cannot connect to %s", rc, vdc.mem_path[i]); } LOG_INFO("vdebug %d connected to %s through %s:%" PRIu16, @@ -754,7 +938,7 @@ static int vdebug_reset(int trst, int srst) static int vdebug_jtag_tms_seq(const uint8_t *tms, int num, uint8_t f_flush) { - LOG_INFO("tms len:%d tms:%x", num, *(const uint32_t *)tms); + LOG_INFO("tms len:%d tms:%x", num, *tms); return vdebug_jtag_shift_tap(vdc.hsocket, pbuf, num, *tms, 0, NULL, 0, 0, NULL, f_flush); } @@ -811,8 +995,8 @@ static int vdebug_jtag_scan(struct scan_command *cmd, uint8_t f_flush) uint8_t cur_tms_post = i == cmd->num_fields - 1 ? tms_post : 0; uint8_t cur_flush = i == cmd->num_fields - 1 ? f_flush : 0; rc = vdebug_jtag_shift_tap(vdc.hsocket, pbuf, cur_num_pre, cur_tms_pre, - cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post, - cmd->fields[i].in_value, cur_flush); + cmd->fields[i].num_bits, cmd->fields[i].out_value, cur_num_post, cur_tms_post, + cmd->fields[i].in_value, cur_flush); if (rc) break; } @@ -913,6 +1097,61 @@ static int vdebug_jtag_execute_queue(void) return rc; } +static int vdebug_dap_connect(struct adiv5_dap *dap) +{ + return dap_dp_init(dap); +} + +static int vdebug_dap_send_sequence(struct adiv5_dap *dap, enum swd_special_seq seq) +{ + return ERROR_OK; +} + +static int vdebug_dap_queue_dp_read(struct adiv5_dap *dap, unsigned int reg, uint32_t *data) +{ + return vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_dp_write(struct adiv5_dap *dap, unsigned int reg, uint32_t data) +{ + return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_ap_read(struct adiv5_ap *ap, unsigned int reg, uint32_t *data) +{ + if ((reg & DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & DP_SELECT_APBANK; + } + + vdebug_reg_read(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, NULL, VD_ASPACE_AP, 0); + + return vdebug_reg_read(vdc.hsocket, pbuf, DP_RDBUFF >> 2, data, VD_ASPACE_DP, 0); +} + +static int vdebug_dap_queue_ap_write(struct adiv5_ap *ap, unsigned int reg, uint32_t data) +{ + if ((reg & DP_SELECT_APBANK) != ap->dap->select) { + vdebug_reg_write(vdc.hsocket, pbuf, DP_SELECT >> 2, reg & DP_SELECT_APBANK, VD_ASPACE_DP, 0); + ap->dap->select = reg & DP_SELECT_APBANK; + } + + return vdebug_reg_write(vdc.hsocket, pbuf, (reg & DP_SELECT_DPBANK) >> 2, data, VD_ASPACE_AP, 0); +} + +static int vdebug_dap_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) +{ + return vdebug_reg_write(vdc.hsocket, pbuf, 0, 0x1, VD_ASPACE_AB, 0); +} + +static int vdebug_dap_run(struct adiv5_dap *dap) +{ + if (pbuf->waddr) + return vdebug_run_reg_queue(vdc.hsocket, pbuf, le_to_h_u16(pbuf->waddr)); + + return ERROR_OK; +} + COMMAND_HANDLER(vdebug_set_server) { if ((CMD_ARGC != 1) || !strchr(CMD_ARGV[0], ':')) @@ -951,7 +1190,10 @@ COMMAND_HANDLER(vdebug_set_bfm) default: break; } - vdc.bfm_type = VD_BFM_JTAG; + if (transport_is_dapdirect_swd()) + vdc.bfm_type = VD_BFM_SWDP; + else + vdc.bfm_type = VD_BFM_JTAG; LOG_DEBUG("bfm_path: %s clk_period %ups", vdc.bfm_path, vdc.bfm_period); return ERROR_OK; @@ -1062,9 +1304,24 @@ static struct jtag_interface vdebug_jtag_ops = { .execute_queue = vdebug_jtag_execute_queue, }; +static const struct dap_ops vdebug_dap_ops = { + .connect = vdebug_dap_connect, + .send_sequence = vdebug_dap_send_sequence, + .queue_dp_read = vdebug_dap_queue_dp_read, + .queue_dp_write = vdebug_dap_queue_dp_write, + .queue_ap_read = vdebug_dap_queue_ap_read, + .queue_ap_write = vdebug_dap_queue_ap_write, + .queue_ap_abort = vdebug_dap_queue_ap_abort, + .run = vdebug_dap_run, + .sync = NULL, /* optional */ + .quit = NULL, /* optional */ +}; + +static const char *const vdebug_transports[] = { "jtag", "dapdirect_swd", NULL }; + struct adapter_driver vdebug_adapter_driver = { .name = "vdebug", - .transports = jtag_only, + .transports = vdebug_transports, .speed = vdebug_jtag_speed, .khz = vdebug_jtag_khz, .speed_div = vdebug_jtag_div, @@ -1073,4 +1330,5 @@ struct adapter_driver vdebug_adapter_driver = { .quit = vdebug_quit, .reset = vdebug_reset, .jtag_ops = &vdebug_jtag_ops, + .dap_swd_ops = &vdebug_dap_ops, }; diff --git a/tcl/board/vd_a53x2_dap.cfg b/tcl/board/vd_a53x2_dap.cfg new file mode 100644 index 0000000000..4cf5594d32 --- /dev/null +++ b/tcl/board/vd_a53x2_dap.cfg @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex A53x2 through DAP + +source [find interface/vdebug.cfg] + +set _CORES 2 +set _CHIPNAME a53 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x1000000 + +# vdebug select transport +transport select dapdirect_swd + +# JTAG reset config, frequency and reset delay +adapter speed 50000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_swdp_bfm 10ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_memory.mem_array $_MEMSTART $_MEMSIZE + +source [find target/swj-dp.tcl] + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf + +source [find target/vd_aarch64.cfg] diff --git a/tcl/board/vd_a53x2_jtag.cfg b/tcl/board/vd_a53x2_jtag.cfg index 869bc4db01..a5e8d24e55 100644 --- a/tcl/board/vd_a53x2_jtag.cfg +++ b/tcl/board/vd_a53x2_jtag.cfg @@ -11,7 +11,7 @@ set _MEMSIZE 0x1000000 set _CPUTAPID 0x5ba00477 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_m4_dap.cfg b/tcl/board/vd_m4_dap.cfg new file mode 100644 index 0000000000..691b6235f6 --- /dev/null +++ b/tcl/board/vd_m4_dap.cfg @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex m4 through DAP + +source [find interface/vdebug.cfg] + +set _CHIPNAME m4 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x10000 + +# vdebug select transport +transport select dapdirect_swd +adapter speed 25000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_swdp_bfm 20ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_mcu.u_sys.u_rom.rom $_MEMSTART $_MEMSIZE + +source [find target/swj-dp.tcl] + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf + +source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_m4_jtag.cfg b/tcl/board/vd_m4_jtag.cfg index ca21476d29..4c795ebfd0 100644 --- a/tcl/board/vd_m4_jtag.cfg +++ b/tcl/board/vd_m4_jtag.cfg @@ -10,7 +10,7 @@ set _MEMSIZE 0x10000 set _CPUTAPID 0x4ba00477 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_m7_jtag.cfg b/tcl/board/vd_m7_jtag.cfg new file mode 100644 index 0000000000..880ef9b4c2 --- /dev/null +++ b/tcl/board/vd_m7_jtag.cfg @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Cadence virtual debug interface +# Arm Cortex m7 through JTAG + +source [find interface/vdebug.cfg] + +set _CHIPNAME m7 +set _MEMSTART 0x00000000 +set _MEMSIZE 0x100000 +set _CPUTAPID 0x0ba02477 + +# vdebug select JTAG transport +transport select jtag + +# JTAG reset config, frequency and reset delay +reset_config trst_and_srst +adapter speed 50000 +adapter srst delay 5 + +# BFM hierarchical path and input clk period +vdebug bfm_path tbench.u_vd_jtag_bfm 10ns + +# DMA Memories to access backdoor (up to 4) +vdebug mem_path tbench.u_mcu.u_sys.u_itcm_ram.Mem $_MEMSTART $_MEMSIZE + +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +jtag arp_init-reset + +source [find target/vd_cortex_m.cfg] diff --git a/tcl/board/vd_pulpissimo_jtag.cfg b/tcl/board/vd_pulpissimo_jtag.cfg index 69dd9e6dbe..a3f5a84886 100644 --- a/tcl/board/vd_pulpissimo_jtag.cfg +++ b/tcl/board/vd_pulpissimo_jtag.cfg @@ -9,7 +9,7 @@ set _HARTID 0x20 set _CPUTAPID 0x249511c3 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/board/vd_swerv_jtag.cfg b/tcl/board/vd_swerv_jtag.cfg index ff6c6835fc..c5d33f268a 100644 --- a/tcl/board/vd_swerv_jtag.cfg +++ b/tcl/board/vd_swerv_jtag.cfg @@ -11,7 +11,7 @@ set _MEMSTART 0x00000000 set _MEMSIZE 0x10000 # vdebug select transport -#transport select jtag +transport select jtag # JTAG reset config, frequency and reset delay reset_config trst_and_srst diff --git a/tcl/target/vd_riscv.cfg b/tcl/target/vd_riscv.cfg index b42b25a3a5..f08cb1ac8b 100644 --- a/tcl/target/vd_riscv.cfg +++ b/tcl/target/vd_riscv.cfg @@ -14,5 +14,4 @@ target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid $_HARTID riscv set_reset_timeout_sec 120 riscv set_command_timeout_sec 120 -# prefer to use sba for system bus access -riscv set_prefer_sba on +riscv set_mem_access sysbus progbuf -- 2.30.2