drivers/vdebug: add support for DAP level interface
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