drivers/vdebug: add support for DAP level interface 65/6965/6
authorJacek Wuwer <jacekmw8@gmail.com>
Wed, 4 May 2022 08:15:57 +0000 (10:15 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 30 Jul 2022 08:48:21 +0000 (08:48 +0000)
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 <jacekmw8@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6965
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
doc/openocd.texi
src/jtag/drivers/vdebug.c
tcl/board/vd_a53x2_dap.cfg [new file with mode: 0644]
tcl/board/vd_a53x2_jtag.cfg
tcl/board/vd_m4_dap.cfg [new file with mode: 0644]
tcl/board/vd_m4_jtag.cfg
tcl/board/vd_m7_jtag.cfg [new file with mode: 0644]
tcl/board/vd_pulpissimo_jtag.cfg
tcl/board/vd_swerv_jtag.cfg
tcl/target/vd_riscv.cfg

index b213798c3172800e94f3087711b784c7e3c536e2..03bb508479d7370ff21bfa02952373afa36ff71b 100644 (file)
@@ -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
index a81740cb1845baf08d88bf7679ca9db738a6ac8f..035c1bee2622969bcc368bd207e0c4c49876fde3 100644 (file)
@@ -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
  *
 */
 
 #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 (file)
index 0000000..4cf5594
--- /dev/null
@@ -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]
index 869bc4db019926d294d062cffa720db58cb66e58..a5e8d24e55622313831aa52019f8c1f352e399aa 100644 (file)
@@ -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 (file)
index 0000000..691b623
--- /dev/null
@@ -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]
index ca21476d29ca260fb6ae390d5f1896b225fadf09..4c795ebfd0a6beadcef2e36b1730684f65150320 100644 (file)
@@ -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 (file)
index 0000000..880ef9b
--- /dev/null
@@ -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]
index 69dd9e6dbef859ff100874fbb6f1c1c464bd1225..a3f5a848865f84248254617571f6a37555532ca8 100644 (file)
@@ -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
index ff6c6835fce2348c18786d17d6b73500c380621a..c5d33f268a8dcdd2f5357b616d93a5b1e3a3218e 100644 (file)
@@ -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
index b42b25a3a5b15c895485b4f5a90e9f0b4769a44e..f08cb1ac8be0148b171ff2065cc58a1c391ca88b 100644 (file)
@@ -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

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)