src/jtag/aice: Fix obviously incorrect bit op.
[openocd.git] / src / jtag / aice / aice_usb.c
index 6b2f87031fd919b4f14652760ef5ebf69793fd80..324ec7c32a651ae43e919b45a00b12939a31e0af 100644 (file)
@@ -13,9 +13,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 /* Global USB buffers */
 static uint8_t usb_in_buffer[AICE_IN_BUFFER_SIZE];
 static uint8_t usb_out_buffer[AICE_OUT_BUFFER_SIZE];
-static uint8_t current_target_id;
 static uint32_t jtag_clock;
 static struct aice_usb_handler_s aice_handler;
 /* AICE max retry times. If AICE command timeout, retry it. */
-static int aice_max_retry_times = 10;
+static int aice_max_retry_times = 50;
 /* Default endian is little endian. */
 static enum aice_target_endian data_endian;
 
+/* Constants for AICE command format length */
+static const int32_t AICE_FORMAT_HTDA = 3;
+static const int32_t AICE_FORMAT_HTDC  = 7;
+static const int32_t AICE_FORMAT_HTDMA = 4;
+static const int32_t AICE_FORMAT_HTDMB = 8;
+static const int32_t AICE_FORMAT_HTDMC = 8;
+static const int32_t AICE_FORMAT_HTDMD = 12;
+static const int32_t AICE_FORMAT_DTHA  = 6;
+static const int32_t AICE_FORMAT_DTHB  = 2;
+static const int32_t AICE_FORMAT_DTHMA = 8;
+static const int32_t AICE_FORMAT_DTHMB = 4;
+
+/* Constants for AICE command */
+static const uint8_t AICE_CMD_SCAN_CHAIN = 0x00;
+static const uint8_t AICE_CMD_T_READ_MISC = 0x20;
+static const uint8_t AICE_CMD_T_READ_EDMSR = 0x21;
+static const uint8_t AICE_CMD_T_READ_DTR = 0x22;
+static const uint8_t AICE_CMD_T_READ_MEM_B = 0x24;
+static const uint8_t AICE_CMD_T_READ_MEM_H = 0x25;
+static const uint8_t AICE_CMD_T_READ_MEM = 0x26;
+static const uint8_t AICE_CMD_T_FASTREAD_MEM = 0x27;
+static const uint8_t AICE_CMD_T_WRITE_MISC = 0x28;
+static const uint8_t AICE_CMD_T_WRITE_EDMSR    = 0x29;
+static const uint8_t AICE_CMD_T_WRITE_DTR = 0x2A;
+static const uint8_t AICE_CMD_T_WRITE_DIM = 0x2B;
+static const uint8_t AICE_CMD_T_WRITE_MEM_B = 0x2C;
+static const uint8_t AICE_CMD_T_WRITE_MEM_H = 0x2D;
+static const uint8_t AICE_CMD_T_WRITE_MEM = 0x2E;
+static const uint8_t AICE_CMD_T_FASTWRITE_MEM = 0x2F;
+static const uint8_t AICE_CMD_T_EXECUTE = 0x3E;
+static const uint8_t AICE_CMD_READ_CTRL = 0x50;
+static const uint8_t AICE_CMD_WRITE_CTRL = 0x51;
+static const uint8_t AICE_CMD_BATCH_BUFFER_READ = 0x60;
+static const uint8_t AICE_CMD_READ_DTR_TO_BUFFER = 0x61;
+static const uint8_t AICE_CMD_BATCH_BUFFER_WRITE = 0x68;
+static const uint8_t AICE_CMD_WRITE_DTR_FROM_BUFFER = 0x69;
 
 /***************************************************************************/
 /* AICE commands' pack/unpack functions */
@@ -359,7 +392,7 @@ static int aice_usb_write(uint8_t *out_buffer, int out_length)
        int result;
 
        if (out_length > AICE_OUT_BUFFER_SIZE) {
-               LOG_ERROR("aice_write illegal out_length=%d (max=%d)",
+               LOG_ERROR("aice_write illegal out_length=%i (max=%i)",
                                out_length, AICE_OUT_BUFFER_SIZE);
                return -1;
        }
@@ -367,7 +400,7 @@ static int aice_usb_write(uint8_t *out_buffer, int out_length)
        result = usb_bulk_write_ex(aice_handler.usb_handle, aice_handler.usb_write_ep,
                        (char *)out_buffer, out_length, AICE_USB_TIMEOUT);
 
-       DEBUG_JTAG_IO("aice_usb_write, out_length = %d, result = %d",
+       LOG_DEBUG_IO("aice_usb_write, out_length = %i, result = %i",
                        out_length, result);
 
        return result;
@@ -376,10 +409,10 @@ static int aice_usb_write(uint8_t *out_buffer, int out_length)
 /* Read data from USB into in_buffer. */
 static int aice_usb_read(uint8_t *in_buffer, int expected_size)
 {
-       int result = usb_bulk_read_ex(aice_handler.usb_handle, aice_handler.usb_read_ep,
+       int32_t result = usb_bulk_read_ex(aice_handler.usb_handle, aice_handler.usb_read_ep,
                        (char *)in_buffer, expected_size, AICE_USB_TIMEOUT);
 
-       DEBUG_JTAG_IO("aice_usb_read, result = %d", result);
+       LOG_DEBUG_IO("aice_usb_read, result = %" PRId32, result);
 
        return result;
 }
@@ -388,49 +421,130 @@ static uint8_t usb_out_packets_buffer[AICE_OUT_PACKETS_BUFFER_SIZE];
 static uint8_t usb_in_packets_buffer[AICE_IN_PACKETS_BUFFER_SIZE];
 static uint32_t usb_out_packets_buffer_length;
 static uint32_t usb_in_packets_buffer_length;
-static bool usb_pack_command;
+static enum aice_command_mode aice_command_mode;
+
+static int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word,
+               uint32_t num_of_words);
 
 static int aice_usb_packet_flush(void)
 {
        if (usb_out_packets_buffer_length == 0)
                return 0;
 
-       LOG_DEBUG("Flush usb packets");
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
+               LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_PACK)");
 
-       int result;
+               if (aice_usb_write(usb_out_packets_buffer,
+                                       usb_out_packets_buffer_length) < 0)
+                       return ERROR_FAIL;
 
-       aice_usb_write(usb_out_packets_buffer, usb_out_packets_buffer_length);
-       result = aice_usb_read(usb_in_packets_buffer, usb_in_packets_buffer_length);
+               if (aice_usb_read(usb_in_packets_buffer,
+                                       usb_in_packets_buffer_length) < 0)
+                       return ERROR_FAIL;
 
-       usb_out_packets_buffer_length = 0;
-       usb_in_packets_buffer_length = 0;
+               usb_out_packets_buffer_length = 0;
+               usb_in_packets_buffer_length = 0;
 
-       return result;
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               LOG_DEBUG("Flush usb packets (AICE_COMMAND_MODE_BATCH)");
+
+               /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
+               if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
+                               usb_out_packets_buffer,
+                               (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
+                       return ERROR_FAIL;
+
+               usb_out_packets_buffer_length = 0;
+               usb_in_packets_buffer_length = 0;
+
+               /* enable BATCH command */
+               aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL, 0x80000000) != ERROR_OK)
+                       return ERROR_FAIL;
+               aice_command_mode = AICE_COMMAND_MODE_BATCH;
+
+               /* wait 1 second (AICE bug, workaround) */
+               alive_sleep(1000);
+
+               /* check status */
+               uint32_t i;
+               uint32_t batch_status;
+
+               i = 0;
+               while (1) {
+                       aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+
+                       if (batch_status & 0x1)
+                               return ERROR_OK;
+                       else if (batch_status & 0xE)
+                               return ERROR_FAIL;
+
+                       if ((i % 30) == 0)
+                               keep_alive();
+
+                       i++;
+               }
+       }
+
+       return ERROR_OK;
 }
 
-static void aice_usb_packet_append(uint8_t *out_buffer, int out_length,
-               int in_length)
+static int aice_usb_packet_append(uint8_t *out_buffer, int out_length, int in_length)
 {
-       if (usb_out_packets_buffer_length + out_length > AICE_OUT_PACKETS_BUFFER_SIZE)
-               aice_usb_packet_flush();
+       uint32_t max_packet_size = AICE_OUT_PACKETS_BUFFER_SIZE;
+
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
+               max_packet_size = AICE_OUT_PACK_COMMAND_SIZE;
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               max_packet_size = AICE_OUT_BATCH_COMMAND_SIZE;
+       } else {
+               /* AICE_COMMAND_MODE_NORMAL */
+               if (aice_usb_packet_flush() != ERROR_OK)
+                       return ERROR_FAIL;
+       }
+
+       if (usb_out_packets_buffer_length + out_length > max_packet_size)
+               if (aice_usb_packet_flush() != ERROR_OK) {
+                       LOG_DEBUG("Flush usb packets failed");
+                       return ERROR_FAIL;
+               }
 
        LOG_DEBUG("Append usb packets 0x%02x", out_buffer[0]);
 
-       memcpy(usb_out_packets_buffer + usb_out_packets_buffer_length,
-                       out_buffer,
-                       out_length);
+       memcpy(usb_out_packets_buffer + usb_out_packets_buffer_length, out_buffer, out_length);
        usb_out_packets_buffer_length += out_length;
        usb_in_packets_buffer_length += in_length;
+
+       return ERROR_OK;
 }
 
 /***************************************************************************/
 /* AICE commands */
+static int aice_reset_box(void)
+{
+       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* turn off FASTMODE */
+       uint32_t pin_status;
+       if (aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status)
+                       != ERROR_OK)
+               return ERROR_FAIL;
+
+       if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x2))
+                       != ERROR_OK)
+               return ERROR_FAIL;
+
+       return ERROR_OK;
+}
+
 static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -443,7 +557,7 @@ static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
                /** TODO: modify receive length */
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
                if (AICE_FORMAT_DTHA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHA, result);
                        return ERROR_FAIL;
                }
@@ -452,27 +566,28 @@ static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
                aice_unpack_dtha_multiple_data(&cmd_ack_code, num_of_ids, id_codes,
                                0x10, AICE_LITTLE_ENDIAN);
 
-               LOG_DEBUG("SCAN_CHAIN response, # of IDs: %d", *num_of_ids);
-
                if (cmd_ack_code != AICE_CMD_SCAN_CHAIN) {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_SCAN_CHAIN, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_SCAN_CHAIN, cmd_ack_code);
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
                        continue;
                }
 
+               LOG_DEBUG("SCAN_CHAIN response, # of IDs: %" PRIu8, *num_of_ids);
+
                if (*num_of_ids == 0xFF) {
                        LOG_ERROR("No target connected");
                        return ERROR_FAIL;
-               } else if (*num_of_ids == 0x10) {
+               } else if (*num_of_ids == AICE_MAX_NUM_CORE) {
                        LOG_INFO("The ice chain over 16 targets");
                } else {
                        (*num_of_ids)++;
@@ -485,20 +600,21 @@ static int aice_scan_chain(uint32_t *id_codes, uint8_t *num_of_ids)
 
 int aice_read_ctrl(uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        aice_pack_htda(AICE_CMD_READ_CTRL, 0, address);
 
        aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDA);
 
-       LOG_DEBUG("READ_CTRL, address: 0x%x", address);
+       LOG_DEBUG("READ_CTRL, address: 0x%" PRIx32, address);
 
        result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHA);
        if (AICE_FORMAT_DTHA != result) {
-               LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+               LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
                                AICE_FORMAT_DTHA, result);
                return ERROR_FAIL;
        }
@@ -507,11 +623,11 @@ int aice_read_ctrl(uint32_t address, uint32_t *data)
        uint8_t extra_length;
        aice_unpack_dtha(&cmd_ack_code, &extra_length, data, AICE_LITTLE_ENDIAN);
 
-       LOG_DEBUG("READ_CTRL response, data: 0x%x", *data);
+       LOG_DEBUG("READ_CTRL response, data: 0x%" PRIx32, *data);
 
        if (cmd_ack_code != AICE_CMD_READ_CTRL) {
-               LOG_ERROR("aice command error (command=0x%x, response=0x%x)",
-                               AICE_CMD_READ_CTRL, cmd_ack_code);
+               LOG_ERROR("aice command error (command=0x%" PRIx32 ", response=0x%" PRIx8 ")",
+                               (uint32_t)AICE_CMD_READ_CTRL, cmd_ack_code);
                return ERROR_FAIL;
        }
 
@@ -520,20 +636,25 @@ int aice_read_ctrl(uint32_t address, uint32_t *data)
 
 int aice_write_ctrl(uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDC,
+                               AICE_FORMAT_DTHB);
+       }
 
        aice_pack_htdc(AICE_CMD_WRITE_CTRL, 0, address, data, AICE_LITTLE_ENDIAN);
 
        aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDC);
 
-       LOG_DEBUG("WRITE_CTRL, address: 0x%x, data: 0x%x", address, data);
+       LOG_DEBUG("WRITE_CTRL, address: 0x%" PRIx32 ", data: 0x%" PRIx32, address, data);
 
        result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHB);
        if (AICE_FORMAT_DTHB != result) {
-               LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+               LOG_ERROR("aice_usb_read failed (requested=%" PRIu32 ", result=%" PRId32 ")",
                                AICE_FORMAT_DTHB, result);
                return ERROR_FAIL;
        }
@@ -545,7 +666,7 @@ int aice_write_ctrl(uint32_t address, uint32_t data)
        LOG_DEBUG("WRITE_CTRL response");
 
        if (cmd_ack_code != AICE_CMD_WRITE_CTRL) {
-               LOG_ERROR("aice command error (command=0x%x, response=0x%x)",
+               LOG_ERROR("aice command error (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
                                AICE_CMD_WRITE_CTRL, cmd_ack_code);
                return ERROR_FAIL;
        }
@@ -555,10 +676,11 @@ int aice_write_ctrl(uint32_t address, uint32_t data)
 
 int aice_read_dtr(uint8_t target_id, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -566,11 +688,11 @@ int aice_read_dtr(uint8_t target_id, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
 
-               LOG_DEBUG("READ_DTR");
+               LOG_DEBUG("READ_DTR, COREID: %" PRIu8, target_id);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_FAIL;
                }
@@ -581,19 +703,71 @@ int aice_read_dtr(uint8_t target_id, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, AICE_LITTLE_ENDIAN);
 
-               LOG_DEBUG("READ_DTR response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_DTR) {
+                       LOG_DEBUG("READ_DTR response, data: 0x%" PRIx32, *data);
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_DTR, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_DTR, cmd_ack_code);
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
+                               return ERROR_FAIL;
+
+                       retry_times++;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+int aice_read_dtr_to_buffer(uint8_t target_id, uint32_t buffer_idx)
+{
+       int32_t result;
+       int retry_times = 0;
+
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
+               aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
+                               AICE_FORMAT_DTHMB);
+       }
+
+       do {
+               aice_pack_htdma(AICE_CMD_READ_DTR_TO_BUFFER, target_id, 0, buffer_idx);
+
+               aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+
+               LOG_DEBUG("READ_DTR_TO_BUFFER, COREID: %" PRIu8, target_id);
+
+               result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+               if (AICE_FORMAT_DTHMB != result) {
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
+                       return ERROR_FAIL;
+               }
+
+               uint8_t cmd_ack_code;
+               uint8_t extra_length;
+               uint8_t res_target_id;
+               aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+
+               if (cmd_ack_code == AICE_CMD_READ_DTR_TO_BUFFER) {
+                       break;
+               } else {
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_READ_DTR_TO_BUFFER, cmd_ack_code);
+
+                               return ERROR_FAIL;
+                       }
+
+                       /* clear timeout and retry */
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -605,24 +779,27 @@ int aice_read_dtr(uint8_t target_id, uint32_t *data)
 
 int aice_write_dtr(uint8_t target_id, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+                               AICE_FORMAT_DTHMB);
+       }
 
        do {
-               aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data,
-                               AICE_LITTLE_ENDIAN);
+               aice_pack_htdmc(AICE_CMD_T_WRITE_DTR, target_id, 0, 0, data, AICE_LITTLE_ENDIAN);
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
 
-               LOG_DEBUG("WRITE_DTR, data: 0x%x", data);
+               LOG_DEBUG("WRITE_DTR, COREID: %" PRIu8 ", data: 0x%" PRIx32, target_id, data);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
-                                       AICE_FORMAT_DTHMB, result);
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
 
@@ -631,19 +808,71 @@ int aice_write_dtr(uint8_t target_id, uint32_t data)
                uint8_t res_target_id;
                aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
 
-               LOG_DEBUG("WRITE_DTR response");
-
                if (cmd_ack_code == AICE_CMD_T_WRITE_DTR) {
+                       LOG_DEBUG("WRITE_DTR response");
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_WRITE_DTR, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_WRITE_DTR, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
+                               return ERROR_FAIL;
+
+                       retry_times++;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+int aice_write_dtr_from_buffer(uint8_t target_id, uint32_t buffer_idx)
+{
+       int32_t result;
+       int retry_times = 0;
+
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
+               aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMA,
+                               AICE_FORMAT_DTHMB);
+       }
+
+       do {
+               aice_pack_htdma(AICE_CMD_WRITE_DTR_FROM_BUFFER, target_id, 0, buffer_idx);
+
+               aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+
+               LOG_DEBUG("WRITE_DTR_FROM_BUFFER, COREID: %" PRIu8 "", target_id);
+
+               result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+               if (AICE_FORMAT_DTHMB != result) {
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
+                       return ERROR_FAIL;
+               }
+
+               uint8_t cmd_ack_code;
+               uint8_t extra_length;
+               uint8_t res_target_id;
+               aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+
+               if (cmd_ack_code == AICE_CMD_WRITE_DTR_FROM_BUFFER) {
+                       break;
+               } else {
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_WRITE_DTR_FROM_BUFFER, cmd_ack_code);
+
+                               return ERROR_FAIL;
+                       }
+
+                       /* clear timeout and retry */
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -655,10 +884,11 @@ int aice_write_dtr(uint8_t target_id, uint32_t data)
 
 int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -666,11 +896,11 @@ int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
 
-               LOG_DEBUG("READ_MISC, address: 0x%x", address);
+               LOG_DEBUG("READ_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_AICE_DISCONNECT;
                }
@@ -681,19 +911,18 @@ int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, AICE_LITTLE_ENDIAN);
 
-               LOG_DEBUG("READ_MISC response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_MISC) {
+                       LOG_DEBUG("READ_MISC response, data: 0x%" PRIx32, *data);
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_MISC, cmd_ack_code);
-
-                       if (retry_times > aice_max_retry_times)
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_MISC, cmd_ack_code);
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -705,11 +934,17 @@ int aice_read_misc(uint8_t target_id, uint32_t address, uint32_t *data)
 
 int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address, data,
+                               AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+                               AICE_FORMAT_DTHMB);
+       }
 
        do {
                aice_pack_htdmc(AICE_CMD_T_WRITE_MISC, target_id, 0, address,
@@ -717,11 +952,12 @@ int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
 
-               LOG_DEBUG("WRITE_MISC, address: 0x%x, data: 0x%x", address, data);
+               LOG_DEBUG("WRITE_MISC, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
+                               target_id, address, data);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
@@ -731,19 +967,19 @@ int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
                uint8_t res_target_id;
                aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
 
-               LOG_DEBUG("WRITE_MISC response");
-
                if (cmd_ack_code == AICE_CMD_T_WRITE_MISC) {
+                       LOG_DEBUG("WRITE_MISC response");
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_WRITE_MISC, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_WRITE_MISC, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -755,10 +991,11 @@ int aice_write_misc(uint8_t target_id, uint32_t address, uint32_t data)
 
 int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -766,11 +1003,11 @@ int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
 
-               LOG_DEBUG("READ_EDMSR, address: 0x%x", address);
+               LOG_DEBUG("READ_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32, target_id, address);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_FAIL;
                }
@@ -781,19 +1018,19 @@ int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, AICE_LITTLE_ENDIAN);
 
-               LOG_DEBUG("READ_EDMSR response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_EDMSR) {
+                       LOG_DEBUG("READ_EDMSR response, data: 0x%" PRIx32, *data);
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_EDMSR, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_EDMSR, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -805,11 +1042,17 @@ int aice_read_edmsr(uint8_t target_id, uint32_t address, uint32_t *data)
 
 int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address, data,
+                               AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMC,
+                               AICE_FORMAT_DTHMB);
+       }
 
        do {
                aice_pack_htdmc(AICE_CMD_T_WRITE_EDMSR, target_id, 0, address,
@@ -817,11 +1060,12 @@ int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
 
-               LOG_DEBUG("WRITE_EDMSR, address: 0x%x, data: 0x%x", address, data);
+               LOG_DEBUG("WRITE_EDMSR, COREID: %" PRIu8 ", address: 0x%" PRIx32 ", data: 0x%" PRIx32,
+                               target_id, address, data);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
@@ -831,19 +1075,19 @@ int aice_write_edmsr(uint8_t target_id, uint32_t address, uint32_t data)
                uint8_t res_target_id;
                aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
 
-               LOG_DEBUG("WRITE_EDMSR response");
-
                if (cmd_ack_code == AICE_CMD_T_WRITE_EDMSR) {
+                       LOG_DEBUG("WRITE_EDMSR response");
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_WRITE_EDMSR, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_WRITE_EDMSR, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -870,26 +1114,34 @@ static int aice_switch_to_big_endian(uint32_t *word, uint8_t num_of_words)
 
 static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_words)
 {
-       int result;
+       int32_t result;
        uint32_t big_endian_word[4];
        int retry_times = 0;
 
-       if (usb_pack_command)
-               aice_usb_packet_flush();
-
-       memcpy(big_endian_word, word, sizeof(big_endian_word));
-
        /** instruction is big-endian */
+       memcpy(big_endian_word, word, sizeof(big_endian_word));
        aice_switch_to_big_endian(big_endian_word, num_of_words);
 
-       do {
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
+               aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
                aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id,
-                               num_of_words - 1, 0,
+                               num_of_words - 1, 0, big_endian_word, num_of_words,
+                               AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer,
+                               AICE_FORMAT_HTDMC + (num_of_words - 1) * 4,
+                               AICE_FORMAT_DTHMB);
+       }
+
+       do {
+               aice_pack_htdmc_multiple_data(AICE_CMD_T_WRITE_DIM, target_id, num_of_words - 1, 0,
                                big_endian_word, num_of_words, AICE_LITTLE_ENDIAN);
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
 
-               LOG_DEBUG("WRITE_DIM, data: 0x%08x, 0x%08x, 0x%08x, 0x%08x",
+               LOG_DEBUG("WRITE_DIM, COREID: %" PRIu8
+                               ", data: 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32 ", 0x%08" PRIx32,
+                               target_id,
                                big_endian_word[0],
                                big_endian_word[1],
                                big_endian_word[2],
@@ -897,8 +1149,7 @@ static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_word
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
-                                       AICE_FORMAT_DTHMB, result);
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
 
@@ -907,19 +1158,21 @@ static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_word
                uint8_t res_target_id;
                aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
 
-               LOG_DEBUG("WRITE_DIM response");
 
                if (cmd_ack_code == AICE_CMD_T_WRITE_DIM) {
+                       LOG_DEBUG("WRITE_DIM response");
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_WRITE_DIM, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8
+                                               ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_WRITE_DIM, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -931,22 +1184,28 @@ static int aice_write_dim(uint8_t target_id, uint32_t *word, uint8_t num_of_word
 
 static int aice_do_execute(uint8_t target_id)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
+               return aice_usb_packet_append(usb_out_buffer,
+                               AICE_FORMAT_HTDMC,
+                               AICE_FORMAT_DTHMB);
+       }
 
        do {
                aice_pack_htdmc(AICE_CMD_T_EXECUTE, target_id, 0, 0, 0, AICE_LITTLE_ENDIAN);
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC);
 
-               LOG_DEBUG("EXECUTE");
+               LOG_DEBUG("EXECUTE, COREID: %" PRIu8 "", target_id);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
@@ -956,19 +1215,19 @@ static int aice_do_execute(uint8_t target_id)
                uint8_t res_target_id;
                aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
 
-               LOG_DEBUG("EXECUTE response");
-
                if (cmd_ack_code == AICE_CMD_T_EXECUTE) {
+                       LOG_DEBUG("EXECUTE response");
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_EXECUTE, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_EXECUTE, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -980,17 +1239,20 @@ static int aice_do_execute(uint8_t target_id)
 
 int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       LOG_DEBUG("WRITE_MEM_B, ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+       LOG_DEBUG("WRITE_MEM_B, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+                       target_id,
                        address,
                        data);
 
-       if (usb_pack_command) {
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
                aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0, address,
                                data & 0x000000FF, data_endian);
-               aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+                               AICE_FORMAT_DTHMB);
        } else {
                do {
                        aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_B, target_id, 0,
@@ -999,8 +1261,8 @@ int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
 
                        result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                        if (AICE_FORMAT_DTHMB != result) {
-                               LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
-                                               AICE_FORMAT_DTHMB, result);
+                               LOG_ERROR("aice_usb_read failed (requested=%" PRId32
+                                               ", result=%" PRId32 ")", AICE_FORMAT_DTHMB, result);
                                return ERROR_FAIL;
                        }
 
@@ -1012,14 +1274,15 @@ int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
                        if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_B) {
                                break;
                        } else {
-                               LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                               AICE_CMD_T_WRITE_MEM_B, cmd_ack_code);
+                               if (retry_times > aice_max_retry_times) {
+                                       LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                                       AICE_CMD_T_WRITE_MEM_B, cmd_ack_code);
 
-                               if (retry_times > aice_max_retry_times)
                                        return ERROR_FAIL;
+                               }
 
                                /* clear timeout and retry */
-                               if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                               if (aice_reset_box() != ERROR_OK)
                                        return ERROR_FAIL;
 
                                retry_times++;
@@ -1032,17 +1295,20 @@ int aice_write_mem_b(uint8_t target_id, uint32_t address, uint32_t data)
 
 int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       LOG_DEBUG("WRITE_MEM_H, ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+       LOG_DEBUG("WRITE_MEM_H, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+                       target_id,
                        address,
                        data);
 
-       if (usb_pack_command) {
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
                aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
                                (address >> 1) & 0x7FFFFFFF, data & 0x0000FFFF, data_endian);
-               aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+                               AICE_FORMAT_DTHMB);
        } else {
                do {
                        aice_pack_htdmd(AICE_CMD_T_WRITE_MEM_H, target_id, 0,
@@ -1051,7 +1317,7 @@ int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
 
                        result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                        if (AICE_FORMAT_DTHMB != result) {
-                               LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                               LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                                AICE_FORMAT_DTHMB, result);
                                return ERROR_FAIL;
                        }
@@ -1064,14 +1330,15 @@ int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
                        if (cmd_ack_code == AICE_CMD_T_WRITE_MEM_H) {
                                break;
                        } else {
-                               LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                               AICE_CMD_T_WRITE_MEM_H, cmd_ack_code);
+                               if (retry_times > aice_max_retry_times) {
+                                       LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                                       AICE_CMD_T_WRITE_MEM_H, cmd_ack_code);
 
-                               if (retry_times > aice_max_retry_times)
                                        return ERROR_FAIL;
+                               }
 
                                /* clear timeout and retry */
-                               if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                               if (aice_reset_box() != ERROR_OK)
                                        return ERROR_FAIL;
 
                                retry_times++;
@@ -1084,17 +1351,20 @@ int aice_write_mem_h(uint8_t target_id, uint32_t address, uint32_t data)
 
 int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       LOG_DEBUG("WRITE_MEM, ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+       LOG_DEBUG("WRITE_MEM, COREID: %" PRIu8 ", ADDRESS %08" PRIx32 "  VALUE %08" PRIx32,
+                       target_id,
                        address,
                        data);
 
-       if (usb_pack_command) {
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode)) {
                aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
                                (address >> 2) & 0x3FFFFFFF, data, data_endian);
-               aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD, AICE_FORMAT_DTHMB);
+               return aice_usb_packet_append(usb_out_buffer, AICE_FORMAT_HTDMD,
+                               AICE_FORMAT_DTHMB);
        } else {
                do {
                        aice_pack_htdmd(AICE_CMD_T_WRITE_MEM, target_id, 0,
@@ -1103,7 +1373,7 @@ int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
 
                        result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                        if (AICE_FORMAT_DTHMB != result) {
-                               LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                               LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                                AICE_FORMAT_DTHMB, result);
                                return ERROR_FAIL;
                        }
@@ -1116,14 +1386,15 @@ int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
                        if (cmd_ack_code == AICE_CMD_T_WRITE_MEM) {
                                break;
                        } else {
-                               LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                               AICE_CMD_T_WRITE_MEM, cmd_ack_code);
+                               if (retry_times > aice_max_retry_times) {
+                                       LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                                       AICE_CMD_T_WRITE_MEM, cmd_ack_code);
 
-                               if (retry_times > aice_max_retry_times)
                                        return ERROR_FAIL;
+                               }
 
                                /* clear timeout and retry */
-                               if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                               if (aice_reset_box() != ERROR_OK)
                                        return ERROR_FAIL;
 
                                retry_times++;
@@ -1136,10 +1407,11 @@ int aice_write_mem(uint8_t target_id, uint32_t address, uint32_t data)
 
 int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -1147,11 +1419,12 @@ int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
 
-               LOG_DEBUG("FASTREAD_MEM, # of DATA %08" PRIx32, num_of_words);
+               LOG_DEBUG("FASTREAD_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
+                               target_id, num_of_words);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
                if (result < 0) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
                        return ERROR_FAIL;
                }
@@ -1165,14 +1438,15 @@ int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
                if (cmd_ack_code == AICE_CMD_T_FASTREAD_MEM) {
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_FASTREAD_MEM, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_FASTREAD_MEM, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -1184,11 +1458,18 @@ int aice_fastread_mem(uint8_t target_id, uint8_t *word, uint32_t num_of_words)
 
 int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_words)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if (AICE_COMMAND_MODE_PACK == aice_command_mode) {
                aice_usb_packet_flush();
+       } else if (AICE_COMMAND_MODE_BATCH == aice_command_mode) {
+               aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
+                               num_of_words - 1, 0, word, data_endian);
+               return aice_usb_packet_append(usb_out_buffer,
+                               AICE_FORMAT_HTDMD + (num_of_words - 1) * 4,
+                               AICE_FORMAT_DTHMB);
+       }
 
        do {
                aice_pack_htdmd_multiple_data(AICE_CMD_T_FASTWRITE_MEM, target_id,
@@ -1196,11 +1477,12 @@ int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_w
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMD + (num_of_words - 1) * 4);
 
-               LOG_DEBUG("FASTWRITE_MEM, # of DATA %08" PRIx32, num_of_words);
+               LOG_DEBUG("FASTWRITE_MEM, COREID: %" PRIu8 ", # of DATA %08" PRIx32,
+                               target_id, num_of_words);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
                if (AICE_FORMAT_DTHMB != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMB, result);
                        return ERROR_FAIL;
                }
@@ -1213,14 +1495,15 @@ int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_w
                if (cmd_ack_code == AICE_CMD_T_FASTWRITE_MEM) {
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_FASTWRITE_MEM, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_FASTWRITE_MEM, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -1232,10 +1515,11 @@ int aice_fastwrite_mem(uint8_t target_id, const uint8_t *word, uint32_t num_of_w
 
 int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -1243,11 +1527,11 @@ int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
 
-               LOG_DEBUG("READ_MEM_B");
+               LOG_DEBUG("READ_MEM_B, COREID: %" PRIu8 "", target_id);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_FAIL;
                }
@@ -1258,19 +1542,19 @@ int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, data_endian);
 
-               LOG_DEBUG("READ_MEM_B response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_MEM_B) {
+                       LOG_DEBUG("READ_MEM_B response, data: 0x%02" PRIx32, *data);
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_MEM_B, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_MEM_B, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -1282,10 +1566,11 @@ int aice_read_mem_b(uint8_t target_id, uint32_t address, uint32_t *data)
 
 int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -1293,11 +1578,11 @@ int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
 
-               LOG_DEBUG("READ_MEM_H");
+               LOG_DEBUG("READ_MEM_H, CORE_ID: %" PRIu8 "", target_id);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_FAIL;
                }
@@ -1308,19 +1593,19 @@ int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, data_endian);
 
-               LOG_DEBUG("READ_MEM_H response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_MEM_H) {
+                       LOG_DEBUG("READ_MEM_H response, data: 0x%" PRIx32, *data);
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_MEM_H, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_MEM_H, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -1332,10 +1617,11 @@ int aice_read_mem_h(uint8_t target_id, uint32_t address, uint32_t *data)
 
 int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
 {
-       int result;
+       int32_t result;
        int retry_times = 0;
 
-       if (usb_pack_command)
+       if ((AICE_COMMAND_MODE_PACK == aice_command_mode) ||
+               (AICE_COMMAND_MODE_BATCH == aice_command_mode))
                aice_usb_packet_flush();
 
        do {
@@ -1344,11 +1630,11 @@ int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
 
                aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMB);
 
-               LOG_DEBUG("READ_MEM");
+               LOG_DEBUG("READ_MEM, COREID: %" PRIu8 "", target_id);
 
                result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA);
                if (AICE_FORMAT_DTHMA != result) {
-                       LOG_ERROR("aice_usb_read failed (requested=%d, result=%d)",
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
                                        AICE_FORMAT_DTHMA, result);
                        return ERROR_FAIL;
                }
@@ -1359,19 +1645,118 @@ int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
                aice_unpack_dthma(&cmd_ack_code, &res_target_id, &extra_length,
                                data, data_endian);
 
-               LOG_DEBUG("READ_MEM response, data: 0x%x", *data);
-
                if (cmd_ack_code == AICE_CMD_T_READ_MEM) {
+                       LOG_DEBUG("READ_MEM response, data: 0x%" PRIx32, *data);
+                       break;
+               } else {
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_T_READ_MEM, cmd_ack_code);
+
+                               return ERROR_FAIL;
+                       }
+
+                       /* clear timeout and retry */
+                       if (aice_reset_box() != ERROR_OK)
+                               return ERROR_FAIL;
+
+                       retry_times++;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+int aice_batch_buffer_read(uint8_t buf_index, uint32_t *word, uint32_t num_of_words)
+{
+       int32_t result;
+       int retry_times = 0;
+
+       do {
+               aice_pack_htdma(AICE_CMD_BATCH_BUFFER_READ, 0, num_of_words - 1, buf_index);
+
+               aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMA);
+
+               LOG_DEBUG("BATCH_BUFFER_READ, # of DATA %08" PRIx32, num_of_words);
+
+               result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMA + (num_of_words - 1) * 4);
+               if (result < 0) {
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
+                                       AICE_FORMAT_DTHMA + (num_of_words - 1) * 4, result);
+                       return ERROR_FAIL;
+               }
+
+               uint8_t cmd_ack_code;
+               uint8_t extra_length;
+               uint8_t res_target_id;
+               aice_unpack_dthma_multiple_data(&cmd_ack_code, &res_target_id,
+                               &extra_length, (uint8_t *)word, data_endian);
+
+               if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_READ) {
+                       break;
+               } else {
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_BATCH_BUFFER_READ, cmd_ack_code);
+
+                               return ERROR_FAIL;
+                       }
+
+                       /* clear timeout and retry */
+                       if (aice_reset_box() != ERROR_OK)
+                               return ERROR_FAIL;
+
+                       retry_times++;
+               }
+       } while (1);
+
+       return ERROR_OK;
+}
+
+int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word, uint32_t num_of_words)
+{
+       int32_t result;
+       int retry_times = 0;
+
+       if (num_of_words == 0)
+               return ERROR_OK;
+
+       do {
+               /* only pack AICE_CMD_BATCH_BUFFER_WRITE command header */
+               aice_pack_htdmc(AICE_CMD_BATCH_BUFFER_WRITE, 0, num_of_words - 1, buf_index,
+                               0, data_endian);
+
+               /* use append instead of pack */
+               memcpy(usb_out_buffer + 4, word, num_of_words * 4);
+
+               aice_usb_write(usb_out_buffer, AICE_FORMAT_HTDMC + (num_of_words - 1) * 4);
+
+               LOG_DEBUG("BATCH_BUFFER_WRITE, # of DATA %08" PRIx32, num_of_words);
+
+               result = aice_usb_read(usb_in_buffer, AICE_FORMAT_DTHMB);
+               if (AICE_FORMAT_DTHMB != result) {
+                       LOG_ERROR("aice_usb_read failed (requested=%" PRId32 ", result=%" PRId32 ")",
+                                       AICE_FORMAT_DTHMB, result);
+                       return ERROR_FAIL;
+               }
+
+               uint8_t cmd_ack_code;
+               uint8_t extra_length;
+               uint8_t res_target_id;
+               aice_unpack_dthmb(&cmd_ack_code, &res_target_id, &extra_length);
+
+               if (cmd_ack_code == AICE_CMD_BATCH_BUFFER_WRITE) {
                        break;
                } else {
-                       LOG_ERROR("aice command timeout (command=0x%x, response=0x%x)",
-                                       AICE_CMD_T_READ_MEM, cmd_ack_code);
+                       if (retry_times > aice_max_retry_times) {
+                               LOG_ERROR("aice command timeout (command=0x%" PRIx8 ", response=0x%" PRIx8 ")",
+                                               AICE_CMD_BATCH_BUFFER_WRITE, cmd_ack_code);
 
-                       if (retry_times > aice_max_retry_times)
                                return ERROR_FAIL;
+                       }
 
                        /* clear timeout and retry */
-                       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+                       if (aice_reset_box() != ERROR_OK)
                                return ERROR_FAIL;
 
                        retry_times++;
@@ -1384,43 +1769,21 @@ int aice_read_mem(uint8_t target_id, uint32_t address, uint32_t *data)
 /***************************************************************************/
 /* End of AICE commands */
 
-typedef int (*read_mem_func_t)(uint32_t address, uint32_t *data);
-typedef int (*write_mem_func_t)(uint32_t address, uint32_t data);
-struct cache_info {
-       uint32_t set;
-       uint32_t way;
-       uint32_t line_size;
+typedef int (*read_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t *data);
+typedef int (*write_mem_func_t)(uint32_t coreid, uint32_t address, uint32_t data);
 
-       uint32_t log2_set;
-       uint32_t log2_line_size;
-};
+struct aice_nds32_info core_info[AICE_MAX_NUM_CORE];
+static uint8_t total_num_of_core;
 
-static uint32_t r0_backup;
-static uint32_t r1_backup;
-static uint32_t host_dtr_backup;
-static uint32_t target_dtr_backup;
-static uint32_t edmsw_backup;
-static uint32_t edm_ctl_backup;
-static bool debug_under_dex_on;
-static bool dex_use_psw_on;
-static bool host_dtr_valid;
-static bool target_dtr_valid;
-static enum nds_memory_access access_channel = NDS_MEMORY_ACC_CPU;
-static enum nds_memory_select memory_select = NDS_MEMORY_SELECT_AUTO;
-static enum aice_target_state_s core_state = AICE_TARGET_UNKNOWN;
-static uint32_t edm_version;
-static struct cache_info icache = {0, 0, 0, 0, 0};
-static struct cache_info dcache = {0, 0, 0, 0, 0};
-static bool cache_init;
 static char *custom_srst_script;
 static char *custom_trst_script;
 static char *custom_restart_script;
 static uint32_t aice_count_to_check_dbger = 30;
 
-static int aice_read_reg(uint32_t num, uint32_t *val);
-static int aice_write_reg(uint32_t num, uint32_t val);
+static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val);
+static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val);
 
-static int check_suppressed_exception(uint32_t dbger_value)
+static int check_suppressed_exception(uint32_t coreid, uint32_t dbger_value)
 {
        uint32_t ir4_value;
        uint32_t ir6_value;
@@ -1434,9 +1797,9 @@ static int check_suppressed_exception(uint32_t dbger_value)
                LOG_ERROR("<-- TARGET WARNING! Exception is detected and suppressed. -->");
                handling_suppressed_exception = true;
 
-               aice_read_reg(IR4, &ir4_value);
+               aice_read_reg(coreid, IR4, &ir4_value);
                /* Clear IR6.SUPRS_EXC, IR6.IMP_EXC */
-               aice_read_reg(IR6, &ir6_value);
+               aice_read_reg(coreid, IR6, &ir6_value);
                /*
                 * For MCU version(MSC_CFG.MCU == 1) like V3m
                 *  | SWID[30:16] | Reserved[15:10] | SUPRS_EXC[9]  | IMP_EXC[8]
@@ -1446,12 +1809,12 @@ static int check_suppressed_exception(uint32_t dbger_value)
                 *  | SWID[30:16] | Reserved[15:14] | SUPRS_EXC[13] | IMP_EXC[12]
                 *  | VECTOR[11:5] | INST[4] | Exc Type[3:0] |
                 */
-               LOG_INFO("EVA: 0x%08x", ir4_value);
-               LOG_INFO("ITYPE: 0x%08x", ir6_value);
+               LOG_INFO("EVA: 0x%08" PRIx32, ir4_value);
+               LOG_INFO("ITYPE: 0x%08" PRIx32, ir6_value);
 
                ir6_value = ir6_value & (~0x300); /* for MCU */
                ir6_value = ir6_value & (~0x3000); /* for non-MCU */
-               aice_write_reg(IR6, ir6_value);
+               aice_write_reg(coreid, IR6, ir6_value);
 
                handling_suppressed_exception = false;
        }
@@ -1459,14 +1822,14 @@ static int check_suppressed_exception(uint32_t dbger_value)
        return ERROR_OK;
 }
 
-static int check_privilege(uint32_t dbger_value)
+static int check_privilege(uint32_t coreid, uint32_t dbger_value)
 {
        if ((dbger_value & NDS_DBGER_ILL_SEC_ACC) == NDS_DBGER_ILL_SEC_ACC) {
                LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege "
                                "to execute the debug operations. -->");
 
                /* Clear DBGER.ILL_SEC_ACC */
-               if (aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER,
+               if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
                                        NDS_DBGER_ILL_SEC_ACC) != ERROR_OK)
                        return ERROR_FAIL;
        }
@@ -1474,29 +1837,32 @@ static int check_privilege(uint32_t dbger_value)
        return ERROR_OK;
 }
 
-static int aice_check_dbger(uint32_t expect_status)
+static int aice_check_dbger(uint32_t coreid, uint32_t expect_status)
 {
        uint32_t i = 0;
        uint32_t value_dbger;
 
        while (1) {
-               aice_read_misc(current_target_id, NDS_EDM_MISC_DBGER, &value_dbger);
+               aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &value_dbger);
 
                if ((value_dbger & expect_status) == expect_status) {
-                       if (ERROR_OK != check_suppressed_exception(value_dbger))
+                       if (ERROR_OK != check_suppressed_exception(coreid, value_dbger))
                                return ERROR_FAIL;
-                       if (ERROR_OK != check_privilege(value_dbger))
+                       if (ERROR_OK != check_privilege(coreid, value_dbger))
                                return ERROR_FAIL;
                        return ERROR_OK;
                }
 
-               long long then = 0;
+               if ((i % 30) == 0)
+                       keep_alive();
+
+               int64_t then = 0;
                if (i == aice_count_to_check_dbger)
                        then = timeval_ms();
                if (i >= aice_count_to_check_dbger) {
                        if ((timeval_ms() - then) > 1000) {
                                LOG_ERROR("Timeout (1000ms) waiting for $DBGER status "
-                                               "being 0x%08x", expect_status);
+                                               "being 0x%08" PRIx32, expect_status);
                                return ERROR_FAIL;
                        }
                }
@@ -1506,24 +1872,24 @@ static int aice_check_dbger(uint32_t expect_status)
        return ERROR_FAIL;
 }
 
-static int aice_execute_dim(uint32_t *insts, uint8_t n_inst)
+static int aice_execute_dim(uint32_t coreid, uint32_t *insts, uint8_t n_inst)
 {
        /** fill DIM */
-       if (aice_write_dim(current_target_id, insts, n_inst) != ERROR_OK)
+       if (aice_write_dim(coreid, insts, n_inst) != ERROR_OK)
                return ERROR_FAIL;
 
        /** clear DBGER.DPED */
-       if (aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
+       if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
                return ERROR_FAIL;
 
        /** execute DIM */
-       if (aice_do_execute(current_target_id) != ERROR_OK)
+       if (aice_do_execute(coreid) != ERROR_OK)
                return ERROR_FAIL;
 
        /** read DBGER.DPED */
-       if (aice_check_dbger(NDS_DBGER_DPED) != ERROR_OK) {
+       if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
                LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly: "
-                               "0x%08x 0x%08x 0x%08x 0x%08x. -->",
+                               "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 "0x%08" PRIx32 ". -->",
                                insts[0],
                                insts[1],
                                insts[2],
@@ -1534,9 +1900,9 @@ static int aice_execute_dim(uint32_t *insts, uint8_t n_inst)
        return ERROR_OK;
 }
 
-static int aice_read_reg(uint32_t num, uint32_t *val)
+static int aice_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
 {
-       LOG_DEBUG("aice_read_reg, reg_no: 0x%08x", num);
+       LOG_DEBUG("aice_read_reg, reg_no: 0x%08" PRIx32, num);
 
        uint32_t instructions[4]; /** execute instructions in DIM */
 
@@ -1593,12 +1959,12 @@ static int aice_read_reg(uint32_t num, uint32_t *val)
                instructions[3] = BEQ_MINUS_12;
        }
 
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
        uint32_t value_edmsw;
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDMSW, &value_edmsw);
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
        if (value_edmsw & NDS_EDMSW_WDV)
-               aice_read_dtr(current_target_id, val);
+               aice_read_dtr(coreid, val);
        else {
                LOG_ERROR("<-- TARGET ERROR! The debug target failed to update "
                                "the DTR register. -->");
@@ -1608,42 +1974,42 @@ static int aice_read_reg(uint32_t num, uint32_t *val)
        return ERROR_OK;
 }
 
-static int aice_usb_read_reg(uint32_t num, uint32_t *val)
+static int aice_usb_read_reg(uint32_t coreid, uint32_t num, uint32_t *val)
 {
        LOG_DEBUG("aice_usb_read_reg");
 
        if (num == R0) {
-               *val = r0_backup;
+               *val = core_info[coreid].r0_backup;
        } else if (num == R1) {
-               *val = r1_backup;
+               *val = core_info[coreid].r1_backup;
        } else if (num == DR41) {
                /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
                 * As user wants to read these registers, OpenOCD should return
                 * the backup values, instead of reading the real values.
                 * As user wants to write these registers, OpenOCD should write
                 * to the backup values, instead of writing to real registers. */
-               *val = edmsw_backup;
+               *val = core_info[coreid].edmsw_backup;
        } else if (num == DR42) {
-               *val = edm_ctl_backup;
-       } else if ((target_dtr_valid == true) && (num == DR43)) {
-               *val = target_dtr_backup;
+               *val = core_info[coreid].edm_ctl_backup;
+       } else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43)) {
+               *val = core_info[coreid].target_dtr_backup;
        } else {
-               if (ERROR_OK != aice_read_reg(num, val))
+               if (ERROR_OK != aice_read_reg(coreid, num, val))
                        *val = 0xBBADBEEF;
        }
 
        return ERROR_OK;
 }
 
-static int aice_write_reg(uint32_t num, uint32_t val)
+static int aice_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
 {
-       LOG_DEBUG("aice_write_reg, reg_no: 0x%08x, value: 0x%08x", num, val);
+       LOG_DEBUG("aice_write_reg, reg_no: 0x%08" PRIx32 ", value: 0x%08" PRIx32, num, val);
 
        uint32_t instructions[4]; /** execute instructions in DIM */
        uint32_t value_edmsw;
 
-       aice_write_dtr(current_target_id, val);
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDMSW, &value_edmsw);
+       aice_write_dtr(coreid, val);
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
        if (0 == (value_edmsw & NDS_EDMSW_RDV)) {
                LOG_ERROR("<-- TARGET ERROR! AICE failed to write to the DTR register. -->");
                return ERROR_FAIL;
@@ -1699,28 +2065,28 @@ static int aice_write_reg(uint32_t num, uint32_t val)
                instructions[3] = BEQ_MINUS_12;
        }
 
-       return aice_execute_dim(instructions, 4);
+       return aice_execute_dim(coreid, instructions, 4);
 }
 
-static int aice_usb_write_reg(uint32_t num, uint32_t val)
+static int aice_usb_write_reg(uint32_t coreid, uint32_t num, uint32_t val)
 {
        LOG_DEBUG("aice_usb_write_reg");
 
        if (num == R0)
-               r0_backup = val;
+               core_info[coreid].r0_backup = val;
        else if (num == R1)
-               r1_backup = val;
+               core_info[coreid].r1_backup = val;
        else if (num == DR42)
                /* As target is halted, OpenOCD will backup DR41/DR42/DR43.
                 * As user wants to read these registers, OpenOCD should return
                 * the backup values, instead of reading the real values.
                 * As user wants to write these registers, OpenOCD should write
                 * to the backup values, instead of writing to real registers. */
-               edm_ctl_backup = val;
-       else if ((target_dtr_valid == true) && (num == DR43))
-               target_dtr_backup = val;
+               core_info[coreid].edm_ctl_backup = val;
+       else if ((core_info[coreid].target_dtr_valid == true) && (num == DR43))
+               core_info[coreid].target_dtr_backup = val;
        else
-               return aice_write_reg(num, val);
+               return aice_write_reg(coreid, num, val);
 
        return ERROR_OK;
 }
@@ -1731,7 +2097,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
        const uint16_t pids[] = { param->pid, 0 };
        struct jtag_libusb_device_handle *devh;
 
-       if (jtag_libusb_open(vids, pids, &devh) != ERROR_OK)
+       if (jtag_libusb_open(vids, pids, NULL, &devh) != ERROR_OK)
                return ERROR_FAIL;
 
        /* BE ***VERY CAREFUL*** ABOUT MAKING CHANGES IN THIS
@@ -1755,7 +2121,7 @@ static int aice_usb_open(struct aice_port_param_s *param)
        /* reopen jlink after usb_reset
         * on win32 this may take a second or two to re-enumerate */
        int retval;
-       while ((retval = jtag_libusb_open(vids, pids, &devh)) != ERROR_OK) {
+       while ((retval = jtag_libusb_open(vids, pids, NULL, &devh)) != ERROR_OK) {
                usleep(1000);
                timeout--;
                if (!timeout)
@@ -1768,13 +2134,14 @@ static int aice_usb_open(struct aice_port_param_s *param)
 #endif
 
        /* usb_set_configuration required under win32 */
-       struct jtag_libusb_device *udev = jtag_libusb_get_device(devh);
        jtag_libusb_set_configuration(devh, 0);
        jtag_libusb_claim_interface(devh, 0);
 
        unsigned int aice_read_ep;
        unsigned int aice_write_ep;
-       jtag_libusb_get_endpoints(udev, &aice_read_ep, &aice_write_ep);
+
+       jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK);
+       LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep);
 
        aice_handler.usb_read_ep = aice_read_ep;
        aice_handler.usb_write_ep = aice_write_ep;
@@ -1783,19 +2150,19 @@ static int aice_usb_open(struct aice_port_param_s *param)
        return ERROR_OK;
 }
 
-static int aice_usb_read_reg_64(uint32_t num, uint64_t *val)
+static int aice_usb_read_reg_64(uint32_t coreid, uint32_t num, uint64_t *val)
 {
        LOG_DEBUG("aice_usb_read_reg_64, %s", nds32_reg_simple_name(num));
 
        uint32_t value;
        uint32_t high_value;
 
-       if (ERROR_OK != aice_read_reg(num, &value))
+       if (ERROR_OK != aice_read_reg(coreid, num, &value))
                value = 0xBBADBEEF;
 
-       aice_read_reg(R1, &high_value);
+       aice_read_reg(coreid, R1, &high_value);
 
-       LOG_DEBUG("low: 0x%08x, high: 0x%08x\n", value, high_value);
+       LOG_DEBUG("low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n", value, high_value);
 
        if (data_endian == AICE_BIG_ENDIAN)
                *val = (((uint64_t)high_value) << 32) | value;
@@ -1805,7 +2172,7 @@ static int aice_usb_read_reg_64(uint32_t num, uint64_t *val)
        return ERROR_OK;
 }
 
-static int aice_usb_write_reg_64(uint32_t num, uint64_t val)
+static int aice_usb_write_reg_64(uint32_t coreid, uint32_t num, uint64_t val)
 {
        uint32_t value;
        uint32_t high_value;
@@ -1818,11 +2185,11 @@ static int aice_usb_write_reg_64(uint32_t num, uint64_t val)
                value = (val >> 32) & 0xFFFFFFFF;
        }
 
-       LOG_DEBUG("aice_usb_write_reg_64, %s, low: 0x%08x, high: 0x%08x\n",
+       LOG_DEBUG("aice_usb_write_reg_64, %s, low: 0x%08" PRIx32 ", high: 0x%08" PRIx32 "\n",
                        nds32_reg_simple_name(num), value, high_value);
 
-       aice_write_reg(R1, high_value);
-       return aice_write_reg(num, value);
+       aice_write_reg(coreid, R1, high_value);
+       return aice_write_reg(coreid, num, value);
 }
 
 static int aice_get_version_info(void)
@@ -1840,7 +2207,7 @@ static int aice_get_version_info(void)
        if (aice_read_ctrl(AICE_READ_CTRL_GET_FPGA_VERSION, &fpga_version) != ERROR_OK)
                return ERROR_FAIL;
 
-       LOG_INFO("AICE version: hw_ver = 0x%x, fw_ver = 0x%x, fpga_ver = 0x%x",
+       LOG_INFO("AICE version: hw_ver = 0x%" PRIx32 ", fw_ver = 0x%" PRIx32 ", fpga_ver = 0x%" PRIx32,
                        hardware_version, firmware_version, fpga_version);
 
        return ERROR_OK;
@@ -1917,47 +2284,41 @@ get_delay:
        return ERROR_OK;
 }
 
-static int aice_edm_reset(void)
-{
-       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
-               return ERROR_FAIL;
-
-       return ERROR_OK;
-}
-
 static int aice_usb_set_clock(int set_clock)
 {
-       if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL,
-                               AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK)
-               return ERROR_FAIL;
+       if (set_clock & AICE_TCK_CONTROL_TCK_SCAN) {
+               if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL,
+                                       AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK)
+                       return ERROR_FAIL;
 
-       /* Read out TCK_SCAN clock value */
-       uint32_t scan_clock;
-       if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK)
-               return ERROR_FAIL;
+               /* Read out TCK_SCAN clock value */
+               uint32_t scan_clock;
+               if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK)
+                       return ERROR_FAIL;
 
-       scan_clock &= 0x0F;
+               scan_clock &= 0x0F;
 
-       uint32_t scan_base_freq;
-       if (scan_clock & 0x8)
-               scan_base_freq = 48000; /* 48 MHz */
-       else
-               scan_base_freq = 30000; /* 30 MHz */
+               uint32_t scan_base_freq;
+               if (scan_clock & 0x8)
+                       scan_base_freq = 48000; /* 48 MHz */
+               else
+                       scan_base_freq = 30000; /* 30 MHz */
 
-       uint32_t set_base_freq;
-       if (set_clock & 0x8)
-               set_base_freq = 48000;
-       else
-               set_base_freq = 30000;
+               uint32_t set_base_freq;
+               if (set_clock & 0x8)
+                       set_base_freq = 48000;
+               else
+                       set_base_freq = 30000;
 
-       uint32_t set_freq;
-       uint32_t scan_freq;
-       set_freq = set_base_freq >> (set_clock & 0x7);
-       scan_freq = scan_base_freq >> (scan_clock & 0x7);
+               uint32_t set_freq;
+               uint32_t scan_freq;
+               set_freq = set_base_freq >> (set_clock & 0x7);
+               scan_freq = scan_base_freq >> (scan_clock & 0x7);
 
-       if (scan_freq < set_freq) {
-               LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock");
-               return ERROR_FAIL;
+               if (scan_freq < set_freq) {
+                       LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock");
+                       return ERROR_FAIL;
+               }
        }
 
        if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, set_clock) != ERROR_OK)
@@ -1975,39 +2336,40 @@ static int aice_usb_set_clock(int set_clock)
        return ERROR_OK;
 }
 
-static int aice_edm_init(void)
+static int aice_edm_init(uint32_t coreid)
 {
-       aice_write_edmsr(current_target_id, NDS_EDM_SR_DIMBR, 0xFFFF0000);
+       aice_write_edmsr(coreid, NDS_EDM_SR_DIMBR, 0xFFFF0000);
+       aice_write_misc(coreid, NDS_EDM_MISC_DIMIR, 0);
 
        /* unconditionally try to turn on V3_EDM_MODE */
        uint32_t edm_ctl_value;
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
-       aice_write_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, edm_ctl_value | 0x00000040);
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
+       aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value | 0x00000040);
 
-       aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER,
+       /* clear DBGER */
+       aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
                        NDS_DBGER_DPED | NDS_DBGER_CRST | NDS_DBGER_AT_MAX);
-       aice_write_misc(current_target_id, NDS_EDM_MISC_DIMIR, 0);
 
        /* get EDM version */
        uint32_t value_edmcfg;
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDM_CFG, &value_edmcfg);
-       edm_version = (value_edmcfg >> 16) & 0xFFFF;
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CFG, &value_edmcfg);
+       core_info[coreid].edm_version = (value_edmcfg >> 16) & 0xFFFF;
 
        return ERROR_OK;
 }
 
-static bool is_v2_edm(void)
+static bool is_v2_edm(uint32_t coreid)
 {
-       if ((edm_version & 0x1000) == 0)
+       if ((core_info[coreid].edm_version & 0x1000) == 0)
                return true;
        else
                return false;
 }
 
-static int aice_init_edm_registers(bool clear_dex_use_psw)
+static int aice_init_edm_registers(uint32_t coreid, bool clear_dex_use_psw)
 {
        /* enable DEH_SEL & MAX_STOP & V3_EDM_MODE & DBGI_MASK */
-       uint32_t host_edm_ctl = edm_ctl_backup | 0xA000004F;
+       uint32_t host_edm_ctl = core_info[coreid].edm_ctl_backup | 0xA000004F;
        if (clear_dex_use_psw)
                /* After entering debug mode, OpenOCD may set
                 * DEX_USE_PSW accidentally through backup value
@@ -2015,9 +2377,9 @@ static int aice_init_edm_registers(bool clear_dex_use_psw)
                 * So, clear DEX_USE_PSW by force. */
                host_edm_ctl &= ~(0x40000000);
 
-       LOG_DEBUG("aice_init_edm_registers - EDM_CTL: 0x%08x", host_edm_ctl);
+       LOG_DEBUG("aice_init_edm_registers - EDM_CTL: 0x%08" PRIx32, host_edm_ctl);
 
-       int result = aice_write_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, host_edm_ctl);
+       int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, host_edm_ctl);
 
        return result;
 }
@@ -2034,9 +2396,10 @@ static int aice_init_edm_registers(bool clear_dex_use_psw)
  * running. The difference of these two scenarios is EDM_CTL.DEH_SEL
  * is on for scenario 1, and off for scenario 2.
  */
-static int aice_backup_edm_registers(void)
+static int aice_backup_edm_registers(uint32_t coreid)
 {
-       int result = aice_read_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, &edm_ctl_backup);
+       int result = aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
+                       &core_info[coreid].edm_ctl_backup);
 
        /* To call aice_backup_edm_registers() after DEX on, DEX_USE_PSW
         * may be not correct.  (For example, hit breakpoint, then backup
@@ -2044,48 +2407,49 @@ static int aice_backup_edm_registers(void)
         * interrupt will clear DEX_USE_PSW, DEX_USE_PSW is always off after
         * DEX is on.  It only backups correct value before OpenOCD issues DBGI.
         * (Backup EDM_CTL, then issue DBGI actively (refer aice_usb_halt())) */
-       if (edm_ctl_backup & 0x40000000)
-               dex_use_psw_on = true;
+       if (core_info[coreid].edm_ctl_backup & 0x40000000)
+               core_info[coreid].dex_use_psw_on = true;
        else
-               dex_use_psw_on = false;
+               core_info[coreid].dex_use_psw_on = false;
 
-       LOG_DEBUG("aice_backup_edm_registers - EDM_CTL: 0x%08x, DEX_USE_PSW: %s",
-                       edm_ctl_backup, dex_use_psw_on ? "on" : "off");
+       LOG_DEBUG("aice_backup_edm_registers - EDM_CTL: 0x%08" PRIx32 ", DEX_USE_PSW: %s",
+                       core_info[coreid].edm_ctl_backup,
+                       core_info[coreid].dex_use_psw_on ? "on" : "off");
 
        return result;
 }
 
-static int aice_restore_edm_registers(void)
+static int aice_restore_edm_registers(uint32_t coreid)
 {
        LOG_DEBUG("aice_restore_edm_registers -");
 
        /* set DEH_SEL, because target still under EDM control */
-       int result = aice_write_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL,
-                       edm_ctl_backup | 0x80000000);
+       int result = aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL,
+                       core_info[coreid].edm_ctl_backup | 0x80000000);
 
        return result;
 }
 
-static int aice_backup_tmp_registers(void)
+static int aice_backup_tmp_registers(uint32_t coreid)
 {
        LOG_DEBUG("backup_tmp_registers -");
 
        /* backup target DTR first(if the target DTR is valid) */
        uint32_t value_edmsw;
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDMSW, &value_edmsw);
-       edmsw_backup = value_edmsw;
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDMSW, &value_edmsw);
+       core_info[coreid].edmsw_backup = value_edmsw;
        if (value_edmsw & 0x1) { /* EDMSW.WDV == 1 */
-               aice_read_dtr(current_target_id, &target_dtr_backup);
-               target_dtr_valid = true;
+               aice_read_dtr(coreid, &core_info[coreid].target_dtr_backup);
+               core_info[coreid].target_dtr_valid = true;
 
-               LOG_DEBUG("Backup target DTR: 0x%08x", target_dtr_backup);
+               LOG_DEBUG("Backup target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
        } else {
-               target_dtr_valid = false;
+               core_info[coreid].target_dtr_valid = false;
        }
 
        /* Target DTR has been backup, then backup $R0 and $R1 */
-       aice_read_reg(R0, &r0_backup);
-       aice_read_reg(R1, &r1_backup);
+       aice_read_reg(coreid, R0, &core_info[coreid].r0_backup);
+       aice_read_reg(coreid, R1, &core_info[coreid].r1_backup);
 
        /* backup host DTR(if the host DTR is valid) */
        if (value_edmsw & 0x2) { /* EDMSW.RDV == 1*/
@@ -2097,50 +2461,52 @@ static int aice_backup_tmp_registers(void)
                        MTSR_DTR(R0),
                        BEQ_MINUS_12
                };
-               aice_execute_dim(instructions, 4);
+               aice_execute_dim(coreid, instructions, 4);
 
-               aice_read_dtr(current_target_id, &host_dtr_backup);
-               host_dtr_valid = true;
+               aice_read_dtr(coreid, &core_info[coreid].host_dtr_backup);
+               core_info[coreid].host_dtr_valid = true;
 
-               LOG_DEBUG("Backup host DTR: 0x%08x", host_dtr_backup);
+               LOG_DEBUG("Backup host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
        } else {
-               host_dtr_valid = false;
+               core_info[coreid].host_dtr_valid = false;
        }
 
-       LOG_DEBUG("r0: 0x%08x, r1: 0x%08x", r0_backup, r1_backup);
+       LOG_DEBUG("r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
+                       core_info[coreid].r0_backup, core_info[coreid].r1_backup);
 
        return ERROR_OK;
 }
 
-static int aice_restore_tmp_registers(void)
+static int aice_restore_tmp_registers(uint32_t coreid)
 {
-       LOG_DEBUG("restore_tmp_registers - r0: 0x%08x, r1: 0x%08x", r0_backup, r1_backup);
+       LOG_DEBUG("restore_tmp_registers - r0: 0x%08" PRIx32 ", r1: 0x%08" PRIx32,
+                       core_info[coreid].r0_backup, core_info[coreid].r1_backup);
 
-       if (target_dtr_valid) {
+       if (core_info[coreid].target_dtr_valid) {
                uint32_t instructions[4] = {
-                       SETHI(R0, target_dtr_backup >> 12),
-                       ORI(R0, R0, target_dtr_backup & 0x00000FFF),
+                       SETHI(R0, core_info[coreid].target_dtr_backup >> 12),
+                       ORI(R0, R0, core_info[coreid].target_dtr_backup & 0x00000FFF),
                        NOP,
                        BEQ_MINUS_12
                };
-               aice_execute_dim(instructions, 4);
+               aice_execute_dim(coreid, instructions, 4);
 
                instructions[0] = MTSR_DTR(R0);
                instructions[1] = DSB;
                instructions[2] = NOP;
                instructions[3] = BEQ_MINUS_12;
-               aice_execute_dim(instructions, 4);
+               aice_execute_dim(coreid, instructions, 4);
 
-               LOG_DEBUG("Restore target DTR: 0x%08x", target_dtr_backup);
+               LOG_DEBUG("Restore target DTR: 0x%08" PRIx32, core_info[coreid].target_dtr_backup);
        }
 
-       aice_write_reg(R0, r0_backup);
-       aice_write_reg(R1, r1_backup);
+       aice_write_reg(coreid, R0, core_info[coreid].r0_backup);
+       aice_write_reg(coreid, R1, core_info[coreid].r1_backup);
 
-       if (host_dtr_valid) {
-               aice_write_dtr(current_target_id, host_dtr_backup);
+       if (core_info[coreid].host_dtr_valid) {
+               aice_write_dtr(coreid, core_info[coreid].host_dtr_backup);
 
-               LOG_DEBUG("Restore host DTR: 0x%08x", host_dtr_backup);
+               LOG_DEBUG("Restore host DTR: 0x%08" PRIx32, core_info[coreid].host_dtr_backup);
        }
 
        return ERROR_OK;
@@ -2159,13 +2525,8 @@ static int aice_open_device(struct aice_port_param_s *param)
        LOG_INFO("AICE initialization started");
 
        /* attempt to reset Andes EDM */
-       if (ERROR_FAIL == aice_edm_reset()) {
-               LOG_ERROR("Cannot initial AICE Interface!");
-               return ERROR_FAIL;
-       }
-
-       if (ERROR_OK != aice_edm_init()) {
-               LOG_ERROR("Cannot initial EDM!");
+       if (ERROR_FAIL == aice_reset_box()) {
+               LOG_ERROR("Cannot initial AICE box!");
                return ERROR_FAIL;
        }
 
@@ -2200,14 +2561,34 @@ static int aice_usb_close(void)
        return ERROR_OK;
 }
 
+static int aice_core_init(uint32_t coreid)
+{
+       core_info[coreid].access_channel = NDS_MEMORY_ACC_CPU;
+       core_info[coreid].memory_select = NDS_MEMORY_SELECT_AUTO;
+       core_info[coreid].core_state = AICE_TARGET_UNKNOWN;
+
+       return ERROR_OK;
+}
+
 static int aice_usb_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
 {
-       return aice_scan_chain(idcode, num_of_idcode);
+       int retval;
+
+       retval = aice_scan_chain(idcode, num_of_idcode);
+       if (ERROR_OK == retval) {
+               for (int i = 0; i < *num_of_idcode; i++) {
+                       aice_core_init(i);
+                       aice_edm_init(i);
+               }
+               total_num_of_core = *num_of_idcode;
+       }
+
+       return retval;
 }
 
-static int aice_usb_halt(void)
+static int aice_usb_halt(uint32_t coreid)
 {
-       if (core_state == AICE_TARGET_HALTED) {
+       if (core_info[coreid].core_state == AICE_TARGET_HALTED) {
                LOG_DEBUG("aice_usb_halt check halted");
                return ERROR_OK;
        }
@@ -2215,54 +2596,54 @@ static int aice_usb_halt(void)
        LOG_DEBUG("aice_usb_halt");
 
        /** backup EDM registers */
-       aice_backup_edm_registers();
+       aice_backup_edm_registers(coreid);
        /** init EDM for host debugging */
        /** no need to clear dex_use_psw, because dbgi will clear it */
-       aice_init_edm_registers(false);
+       aice_init_edm_registers(coreid, false);
 
        /** Clear EDM_CTL.DBGIM & EDM_CTL.DBGACKM */
        uint32_t edm_ctl_value;
-       aice_read_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
+       aice_read_edmsr(coreid, NDS_EDM_SR_EDM_CTL, &edm_ctl_value);
        if (edm_ctl_value & 0x3)
-               aice_write_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
+               aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value & ~(0x3));
 
        uint32_t dbger;
        uint32_t acc_ctl_value;
 
-       debug_under_dex_on = false;
-       aice_read_misc(current_target_id, NDS_EDM_MISC_DBGER, &dbger);
+       core_info[coreid].debug_under_dex_on = false;
+       aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger);
 
        if (dbger & NDS_DBGER_AT_MAX)
                LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level. -->");
 
        if (dbger & NDS_DBGER_DEX) {
-               if (is_v2_edm() == false) {
+               if (is_v2_edm(coreid) == false) {
                        /** debug 'debug mode'. use force_debug to issue dbgi */
-                       aice_read_misc(current_target_id, NDS_EDM_MISC_ACC_CTL, &acc_ctl_value);
+                       aice_read_misc(coreid, NDS_EDM_MISC_ACC_CTL, &acc_ctl_value);
                        acc_ctl_value |= 0x8;
-                       aice_write_misc(current_target_id, NDS_EDM_MISC_ACC_CTL, acc_ctl_value);
-                       debug_under_dex_on = true;
+                       aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL, acc_ctl_value);
+                       core_info[coreid].debug_under_dex_on = true;
 
-                       aice_write_misc(current_target_id, NDS_EDM_MISC_EDM_CMDR, 0);
+                       aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
                        /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
                        if (dbger & NDS_DBGER_AT_MAX)
-                               aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
+                               aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
                }
        } else {
                /** Issue DBGI normally */
-               aice_write_misc(current_target_id, NDS_EDM_MISC_EDM_CMDR, 0);
+               aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0);
                /* If CPU stalled due to AT_MAX, clear AT_MAX status. */
                if (dbger & NDS_DBGER_AT_MAX)
-                       aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
+                       aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_AT_MAX);
        }
 
-       if (aice_check_dbger(NDS_DBGER_DEX) != ERROR_OK) {
+       if (aice_check_dbger(coreid, NDS_DBGER_DEX) != ERROR_OK) {
                LOG_ERROR("<-- TARGET ERROR! Unable to stop the debug target through DBGI. -->");
                return ERROR_FAIL;
        }
 
-       if (debug_under_dex_on) {
-               if (dex_use_psw_on == false) {
+       if (core_info[coreid].debug_under_dex_on) {
+               if (core_info[coreid].dex_use_psw_on == false) {
                        /* under debug 'debug mode', force $psw to 'debug mode' bahavior */
                        /* !!!NOTICE!!! this is workaround for debug 'debug mode'.
                         * it is only for debugging 'debug exception handler' purpose.
@@ -2270,30 +2651,30 @@ static int aice_usb_halt(void)
                         * undefined. */
                        uint32_t ir0_value;
                        uint32_t debug_mode_ir0_value;
-                       aice_read_reg(IR0, &ir0_value);
+                       aice_read_reg(coreid, IR0, &ir0_value);
                        debug_mode_ir0_value = ir0_value | 0x408; /* turn on DEX, set POM = 1 */
                        debug_mode_ir0_value &= ~(0x000000C1); /* turn off DT/IT/GIE */
-                       aice_write_reg(IR0, debug_mode_ir0_value);
+                       aice_write_reg(coreid, IR0, debug_mode_ir0_value);
                }
        }
 
        /** set EDM_CTL.DBGIM & EDM_CTL.DBGACKM after halt */
        if (edm_ctl_value & 0x3)
-               aice_write_edmsr(current_target_id, NDS_EDM_SR_EDM_CTL, edm_ctl_value);
+               aice_write_edmsr(coreid, NDS_EDM_SR_EDM_CTL, edm_ctl_value);
 
        /* backup r0 & r1 */
-       aice_backup_tmp_registers();
-       core_state = AICE_TARGET_HALTED;
+       aice_backup_tmp_registers(coreid);
+       core_info[coreid].core_state = AICE_TARGET_HALTED;
 
        return ERROR_OK;
 }
 
-static int aice_usb_state(enum aice_target_state_s *state)
+static int aice_usb_state(uint32_t coreid, enum aice_target_state_s *state)
 {
        uint32_t dbger_value;
        uint32_t ice_state;
 
-       int result = aice_read_misc(current_target_id, NDS_EDM_MISC_DBGER, &dbger_value);
+       int result = aice_read_misc(coreid, NDS_EDM_MISC_DBGER, &dbger_value);
 
        if (ERROR_AICE_TIMEOUT == result) {
                if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &ice_state) != ERROR_OK) {
@@ -2316,47 +2697,47 @@ static int aice_usb_state(enum aice_target_state_s *state)
                LOG_ERROR("<-- TARGET ERROR! Insufficient security privilege. -->");
 
                /* Clear ILL_SEC_ACC */
-               aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC);
+               aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_ILL_SEC_ACC);
 
                *state = AICE_TARGET_RUNNING;
-               core_state = AICE_TARGET_RUNNING;
+               core_info[coreid].core_state = AICE_TARGET_RUNNING;
        } else if ((dbger_value & NDS_DBGER_AT_MAX) == NDS_DBGER_AT_MAX) {
                /* Issue DBGI to exit cpu stall */
-               aice_usb_halt();
+               aice_usb_halt(coreid);
 
                /* Read OIPC to find out the trigger point */
                uint32_t ir11_value;
-               aice_read_reg(IR11, &ir11_value);
+               aice_read_reg(coreid, IR11, &ir11_value);
 
                LOG_ERROR("<-- TARGET ERROR! Reaching the max interrupt stack level; "
-                               "CPU is stalled at 0x%08x for debugging. -->", ir11_value);
+                               "CPU is stalled at 0x%08" PRIx32 " for debugging. -->", ir11_value);
 
                *state = AICE_TARGET_HALTED;
        } else if ((dbger_value & NDS_DBGER_CRST) == NDS_DBGER_CRST) {
                LOG_DEBUG("DBGER.CRST is on.");
 
                *state = AICE_TARGET_RESET;
-               core_state = AICE_TARGET_RUNNING;
+               core_info[coreid].core_state = AICE_TARGET_RUNNING;
 
                /* Clear CRST */
-               aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST);
+               aice_write_misc(coreid, NDS_EDM_MISC_DBGER, NDS_DBGER_CRST);
        } else if ((dbger_value & NDS_DBGER_DEX) == NDS_DBGER_DEX) {
-               if (AICE_TARGET_RUNNING == core_state) {
+               if (AICE_TARGET_RUNNING == core_info[coreid].core_state) {
                        /* enter debug mode, init EDM registers */
                        /* backup EDM registers */
-                       aice_backup_edm_registers();
+                       aice_backup_edm_registers(coreid);
                        /* init EDM for host debugging */
-                       aice_init_edm_registers(true);
-                       aice_backup_tmp_registers();
-                       core_state = AICE_TARGET_HALTED;
-               } else if (AICE_TARGET_UNKNOWN == core_state) {
+                       aice_init_edm_registers(coreid, true);
+                       aice_backup_tmp_registers(coreid);
+                       core_info[coreid].core_state = AICE_TARGET_HALTED;
+               } else if (AICE_TARGET_UNKNOWN == core_info[coreid].core_state) {
                        /* debug 'debug mode', use force debug to halt core */
-                       aice_usb_halt();
+                       aice_usb_halt(coreid);
                }
                *state = AICE_TARGET_HALTED;
        } else {
                *state = AICE_TARGET_RUNNING;
-               core_state = AICE_TARGET_RUNNING;
+               core_info[coreid].core_state = AICE_TARGET_RUNNING;
        }
 
        return ERROR_OK;
@@ -2364,9 +2745,10 @@ static int aice_usb_state(enum aice_target_state_s *state)
 
 static int aice_usb_reset(void)
 {
-       if (aice_write_ctrl(AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS, 0x1) != ERROR_OK)
+       if (aice_reset_box() != ERROR_OK)
                return ERROR_FAIL;
 
+       /* issue TRST */
        if (custom_trst_script == NULL) {
                if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
                                        AICE_JTAG_PIN_CONTROL_TRST) != ERROR_OK)
@@ -2383,12 +2765,12 @@ static int aice_usb_reset(void)
        return ERROR_OK;
 }
 
-static int aice_issue_srst(void)
+static int aice_issue_srst(uint32_t coreid)
 {
        LOG_DEBUG("aice_issue_srst");
 
        /* After issuing srst, target will be running. So we need to restore EDM_CTL. */
-       aice_restore_edm_registers();
+       aice_restore_edm_registers(coreid);
 
        if (custom_srst_script == NULL) {
                if (aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_CONTROL,
@@ -2404,7 +2786,7 @@ static int aice_issue_srst(void)
        uint32_t dbger_value;
        int i = 0;
        while (1) {
-               if (aice_read_misc(current_target_id,
+               if (aice_read_misc(coreid,
                                        NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
                        return ERROR_FAIL;
 
@@ -2416,21 +2798,21 @@ static int aice_issue_srst(void)
                i++;
        }
 
-       host_dtr_valid = false;
-       target_dtr_valid = false;
+       core_info[coreid].host_dtr_valid = false;
+       core_info[coreid].target_dtr_valid = false;
 
-       core_state = AICE_TARGET_RUNNING;
+       core_info[coreid].core_state = AICE_TARGET_RUNNING;
        return ERROR_OK;
 }
 
-static int aice_issue_reset_hold(void)
+static int aice_issue_reset_hold(uint32_t coreid)
 {
        LOG_DEBUG("aice_issue_reset_hold");
 
        /* set no_dbgi_pin to 0 */
        uint32_t pin_status;
        aice_read_ctrl(AICE_READ_CTRL_GET_JTAG_PIN_STATUS, &pin_status);
-       if (pin_status | 0x4)
+       if (pin_status & 0x4)
                aice_write_ctrl(AICE_WRITE_CTRL_JTAG_PIN_STATUS, pin_status & (~0x4));
 
        /* issue restart */
@@ -2444,9 +2826,9 @@ static int aice_issue_reset_hold(void)
                        return ERROR_FAIL;
        }
 
-       if (aice_check_dbger(NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
-               aice_backup_tmp_registers();
-               core_state = AICE_TARGET_HALTED;
+       if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
+               aice_backup_tmp_registers(coreid);
+               core_info[coreid].core_state = AICE_TARGET_HALTED;
 
                return ERROR_OK;
        } else {
@@ -2464,58 +2846,89 @@ static int aice_issue_reset_hold(void)
                                return ERROR_FAIL;
                }
 
-               if (aice_check_dbger(NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
-                       aice_backup_tmp_registers();
-                       core_state = AICE_TARGET_HALTED;
+               if (aice_check_dbger(coreid, NDS_DBGER_CRST | NDS_DBGER_DEX) == ERROR_OK) {
+                       aice_backup_tmp_registers(coreid);
+                       core_info[coreid].core_state = AICE_TARGET_HALTED;
 
                        return ERROR_OK;
                }
 
                /* do software reset-and-hold */
-               aice_issue_srst();
-               aice_usb_halt();
+               aice_issue_srst(coreid);
+               aice_usb_halt(coreid);
 
                uint32_t value_ir3;
-               aice_read_reg(IR3, &value_ir3);
-               aice_write_reg(PC, value_ir3 & 0xFFFF0000);
+               aice_read_reg(coreid, IR3, &value_ir3);
+               aice_write_reg(coreid, PC, value_ir3 & 0xFFFF0000);
        }
 
        return ERROR_FAIL;
 }
 
-static int aice_usb_assert_srst(enum aice_srst_type_s srst)
+static int aice_issue_reset_hold_multi(void)
+{
+       uint32_t write_ctrl_value = 0;
+
+       /* set SRST */
+       write_ctrl_value = AICE_CUSTOM_DELAY_SET_SRST;
+       write_ctrl_value |= (0x200 << 16);
+       if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
+                               write_ctrl_value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       for (uint8_t i = 0 ; i < total_num_of_core ; i++)
+               aice_write_misc(i, NDS_EDM_MISC_EDM_CMDR, 0);
+
+       /* clear SRST */
+       write_ctrl_value = AICE_CUSTOM_DELAY_CLEAN_SRST;
+       write_ctrl_value |= (0x200 << 16);
+       if (aice_write_ctrl(AICE_WRITE_CTRL_CUSTOM_DELAY,
+                               write_ctrl_value) != ERROR_OK)
+               return ERROR_FAIL;
+
+       for (uint8_t i = 0; i < total_num_of_core; i++)
+               aice_edm_init(i);
+
+       return ERROR_FAIL;
+}
+
+static int aice_usb_assert_srst(uint32_t coreid, enum aice_srst_type_s srst)
 {
        if ((AICE_SRST != srst) && (AICE_RESET_HOLD != srst))
                return ERROR_FAIL;
 
        /* clear DBGER */
-       if (aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER,
+       if (aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
                                NDS_DBGER_CLEAR_ALL) != ERROR_OK)
                return ERROR_FAIL;
 
        int result = ERROR_OK;
        if (AICE_SRST == srst)
-               result = aice_issue_srst();
-       else
-               result = aice_issue_reset_hold();
+               result = aice_issue_srst(coreid);
+       else {
+               if (1 == total_num_of_core)
+                       result = aice_issue_reset_hold(coreid);
+               else
+                       result = aice_issue_reset_hold_multi();
+       }
 
        /* Clear DBGER.CRST after reset to avoid 'core-reset checking' errors.
         * assert_srst is user-intentional reset behavior, so we could
         * clear DBGER.CRST safely.
         */
-       if (aice_write_misc(current_target_id,
+       if (aice_write_misc(coreid,
                                NDS_EDM_MISC_DBGER, NDS_DBGER_CRST) != ERROR_OK)
                return ERROR_FAIL;
 
        return result;
 }
 
-static int aice_usb_run(void)
+static int aice_usb_run(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_run");
 
        uint32_t dbger_value;
-       if (aice_read_misc(current_target_id,
+       if (aice_read_misc(coreid,
                                NDS_EDM_MISC_DBGER, &dbger_value) != ERROR_OK)
                return ERROR_FAIL;
 
@@ -2526,11 +2939,11 @@ static int aice_usb_run(void)
        }
 
        /* restore r0 & r1 before free run */
-       aice_restore_tmp_registers();
-       core_state = AICE_TARGET_RUNNING;
+       aice_restore_tmp_registers(coreid);
+       core_info[coreid].core_state = AICE_TARGET_RUNNING;
 
        /* clear DBGER */
-       aice_write_misc(current_target_id, NDS_EDM_MISC_DBGER,
+       aice_write_misc(coreid, NDS_EDM_MISC_DBGER,
                        NDS_DBGER_CLEAR_ALL);
 
        /** restore EDM registers */
@@ -2541,7 +2954,7 @@ static int aice_usb_run(void)
         *        slli $p0, $p0, 1
         *        slri $p0, $p0, 31
         */
-       aice_restore_edm_registers();
+       aice_restore_edm_registers(coreid);
 
        /** execute instructions in DIM */
        uint32_t instructions[4] = {
@@ -2550,46 +2963,46 @@ static int aice_usb_run(void)
                NOP,
                IRET
        };
-       int result = aice_execute_dim(instructions, 4);
+       int result = aice_execute_dim(coreid, instructions, 4);
 
        return result;
 }
 
-static int aice_usb_step(void)
+static int aice_usb_step(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_step");
 
        uint32_t ir0_value;
        uint32_t ir0_reg_num;
 
-       if (is_v2_edm() == true)
+       if (is_v2_edm(coreid) == true)
                /* V2 EDM will push interrupt stack as debug exception */
                ir0_reg_num = IR1;
        else
                ir0_reg_num = IR0;
 
        /** enable HSS */
-       aice_read_reg(ir0_reg_num, &ir0_value);
+       aice_read_reg(coreid, ir0_reg_num, &ir0_value);
        if ((ir0_value & 0x800) == 0) {
                /** set PSW.HSS */
                ir0_value |= (0x01 << 11);
-               aice_write_reg(ir0_reg_num, ir0_value);
+               aice_write_reg(coreid, ir0_reg_num, ir0_value);
        }
 
-       if (ERROR_FAIL == aice_usb_run())
+       if (ERROR_FAIL == aice_usb_run(coreid))
                return ERROR_FAIL;
 
        int i = 0;
        enum aice_target_state_s state;
        while (1) {
                /* read DBGER */
-               if (aice_usb_state(&state) != ERROR_OK)
+               if (aice_usb_state(coreid, &state) != ERROR_OK)
                        return ERROR_FAIL;
 
                if (AICE_TARGET_HALTED == state)
                        break;
 
-               long long then = 0;
+               int64_t then = 0;
                if (i == 30)
                        then = timeval_ms();
 
@@ -2603,29 +3016,29 @@ static int aice_usb_step(void)
        }
 
        /** disable HSS */
-       aice_read_reg(ir0_reg_num, &ir0_value);
+       aice_read_reg(coreid, ir0_reg_num, &ir0_value);
        ir0_value &= ~(0x01 << 11);
-       aice_write_reg(ir0_reg_num, ir0_value);
+       aice_write_reg(coreid, ir0_reg_num, ir0_value);
 
        return ERROR_OK;
 }
 
-static int aice_usb_read_mem_b_bus(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t *data)
 {
-       return aice_read_mem_b(current_target_id, address, data);
+       return aice_read_mem_b(coreid, address, data);
 }
 
-static int aice_usb_read_mem_h_bus(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t *data)
 {
-       return aice_read_mem_h(current_target_id, address, data);
+       return aice_read_mem_h(coreid, address, data);
 }
 
-static int aice_usb_read_mem_w_bus(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t *data)
 {
-       return aice_read_mem(current_target_id, address, data);
+       return aice_read_mem(coreid, address, data);
 }
 
-static int aice_usb_read_mem_b_dim(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t *data)
 {
        uint32_t value;
        uint32_t instructions[4] = {
@@ -2635,15 +3048,15 @@ static int aice_usb_read_mem_b_dim(uint32_t address, uint32_t *data)
                BEQ_MINUS_12
        };
 
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
-       aice_read_dtr(current_target_id, &value);
+       aice_read_dtr(coreid, &value);
        *data = value & 0xFF;
 
        return ERROR_OK;
 }
 
-static int aice_usb_read_mem_h_dim(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t *data)
 {
        uint32_t value;
        uint32_t instructions[4] = {
@@ -2653,15 +3066,15 @@ static int aice_usb_read_mem_h_dim(uint32_t address, uint32_t *data)
                BEQ_MINUS_12
        };
 
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
-       aice_read_dtr(current_target_id, &value);
+       aice_read_dtr(coreid, &value);
        *data = value & 0xFFFF;
 
        return ERROR_OK;
 }
 
-static int aice_usb_read_mem_w_dim(uint32_t address, uint32_t *data)
+static int aice_usb_read_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t *data)
 {
        uint32_t instructions[4] = {
                LWI_BI(R1, R0),
@@ -2670,14 +3083,14 @@ static int aice_usb_read_mem_w_dim(uint32_t address, uint32_t *data)
                BEQ_MINUS_12
        };
 
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
-       aice_read_dtr(current_target_id, data);
+       aice_read_dtr(coreid, data);
 
        return ERROR_OK;
 }
 
-static int aice_usb_set_address_dim(uint32_t address)
+static int aice_usb_set_address_dim(uint32_t coreid, uint32_t address)
 {
        uint32_t instructions[4] = {
                SETHI(R0, address >> 12),
@@ -2686,17 +3099,18 @@ static int aice_usb_set_address_dim(uint32_t address)
                BEQ_MINUS_12
        };
 
-       return aice_execute_dim(instructions, 4);
+       return aice_execute_dim(coreid, instructions, 4);
 }
 
-static int aice_usb_read_memory_unit(uint32_t addr, uint32_t size,
+static int aice_usb_read_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
                uint32_t count, uint8_t *buffer)
 {
-       LOG_DEBUG("aice_usb_read_memory_unit, addr: 0x%08x, size: %d, count: %d",
+       LOG_DEBUG("aice_usb_read_memory_unit, addr: 0x%08" PRIx32
+                       ", size: %" PRIu32 ", count: %" PRIu32 "",
                        addr, size, count);
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               aice_usb_set_address_dim(addr);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               aice_usb_set_address_dim(coreid, addr);
 
        uint32_t value;
        size_t i;
@@ -2704,25 +3118,25 @@ static int aice_usb_read_memory_unit(uint32_t addr, uint32_t size,
 
        switch (size) {
                case 1:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                read_mem_func = aice_usb_read_mem_b_bus;
                        else
                                read_mem_func = aice_usb_read_mem_b_dim;
 
                        for (i = 0; i < count; i++) {
-                               read_mem_func(addr, &value);
+                               read_mem_func(coreid, addr, &value);
                                *buffer++ = (uint8_t)value;
                                addr++;
                        }
                        break;
                case 2:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                read_mem_func = aice_usb_read_mem_h_bus;
                        else
                                read_mem_func = aice_usb_read_mem_h_dim;
 
                        for (i = 0; i < count; i++) {
-                               read_mem_func(addr, &value);
+                               read_mem_func(coreid, addr, &value);
                                uint16_t svalue = value;
                                memcpy(buffer, &svalue, sizeof(uint16_t));
                                buffer += 2;
@@ -2730,13 +3144,13 @@ static int aice_usb_read_memory_unit(uint32_t addr, uint32_t size,
                        }
                        break;
                case 4:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                read_mem_func = aice_usb_read_mem_w_bus;
                        else
                                read_mem_func = aice_usb_read_mem_w_dim;
 
                        for (i = 0; i < count; i++) {
-                               read_mem_func(addr, &value);
+                               read_mem_func(coreid, addr, &value);
                                memcpy(buffer, &value, sizeof(uint32_t));
                                buffer += 4;
                                addr += 4;
@@ -2747,22 +3161,22 @@ static int aice_usb_read_memory_unit(uint32_t addr, uint32_t size,
        return ERROR_OK;
 }
 
-static int aice_usb_write_mem_b_bus(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_b_bus(uint32_t coreid, uint32_t address, uint32_t data)
 {
-       return aice_write_mem_b(current_target_id, address, data);
+       return aice_write_mem_b(coreid, address, data);
 }
 
-static int aice_usb_write_mem_h_bus(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_h_bus(uint32_t coreid, uint32_t address, uint32_t data)
 {
-       return aice_write_mem_h(current_target_id, address, data);
+       return aice_write_mem_h(coreid, address, data);
 }
 
-static int aice_usb_write_mem_w_bus(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_w_bus(uint32_t coreid, uint32_t address, uint32_t data)
 {
-       return aice_write_mem(current_target_id, address, data);
+       return aice_write_mem(coreid, address, data);
 }
 
-static int aice_usb_write_mem_b_dim(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_b_dim(uint32_t coreid, uint32_t address, uint32_t data)
 {
        uint32_t instructions[4] = {
                MFSR_DTR(R1),
@@ -2771,13 +3185,13 @@ static int aice_usb_write_mem_b_dim(uint32_t address, uint32_t data)
                BEQ_MINUS_12
        };
 
-       aice_write_dtr(current_target_id, data & 0xFF);
-       aice_execute_dim(instructions, 4);
+       aice_write_dtr(coreid, data & 0xFF);
+       aice_execute_dim(coreid, instructions, 4);
 
        return ERROR_OK;
 }
 
-static int aice_usb_write_mem_h_dim(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_h_dim(uint32_t coreid, uint32_t address, uint32_t data)
 {
        uint32_t instructions[4] = {
                MFSR_DTR(R1),
@@ -2786,13 +3200,13 @@ static int aice_usb_write_mem_h_dim(uint32_t address, uint32_t data)
                BEQ_MINUS_12
        };
 
-       aice_write_dtr(current_target_id, data & 0xFFFF);
-       aice_execute_dim(instructions, 4);
+       aice_write_dtr(coreid, data & 0xFFFF);
+       aice_execute_dim(coreid, instructions, 4);
 
        return ERROR_OK;
 }
 
-static int aice_usb_write_mem_w_dim(uint32_t address, uint32_t data)
+static int aice_usb_write_mem_w_dim(uint32_t coreid, uint32_t address, uint32_t data)
 {
        uint32_t instructions[4] = {
                MFSR_DTR(R1),
@@ -2801,39 +3215,40 @@ static int aice_usb_write_mem_w_dim(uint32_t address, uint32_t data)
                BEQ_MINUS_12
        };
 
-       aice_write_dtr(current_target_id, data);
-       aice_execute_dim(instructions, 4);
+       aice_write_dtr(coreid, data);
+       aice_execute_dim(coreid, instructions, 4);
 
        return ERROR_OK;
 }
 
-static int aice_usb_write_memory_unit(uint32_t addr, uint32_t size,
+static int aice_usb_write_memory_unit(uint32_t coreid, uint32_t addr, uint32_t size,
                uint32_t count, const uint8_t *buffer)
 {
-       LOG_DEBUG("aice_usb_write_memory_unit, addr: 0x%08x, size: %d, count: %d",
+       LOG_DEBUG("aice_usb_write_memory_unit, addr: 0x%08" PRIx32
+                       ", size: %" PRIu32 ", count: %" PRIu32 "",
                        addr, size, count);
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               aice_usb_set_address_dim(addr);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               aice_usb_set_address_dim(coreid, addr);
 
        size_t i;
        write_mem_func_t write_mem_func;
 
        switch (size) {
                case 1:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                write_mem_func = aice_usb_write_mem_b_bus;
                        else
                                write_mem_func = aice_usb_write_mem_b_dim;
 
                        for (i = 0; i < count; i++) {
-                               write_mem_func(addr, *buffer);
+                               write_mem_func(coreid, addr, *buffer);
                                buffer++;
                                addr++;
                        }
                        break;
                case 2:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                write_mem_func = aice_usb_write_mem_h_bus;
                        else
                                write_mem_func = aice_usb_write_mem_h_dim;
@@ -2842,13 +3257,13 @@ static int aice_usb_write_memory_unit(uint32_t addr, uint32_t size,
                                uint16_t value;
                                memcpy(&value, buffer, sizeof(uint16_t));
 
-                               write_mem_func(addr, value);
+                               write_mem_func(coreid, addr, value);
                                buffer += 2;
                                addr += 2;
                        }
                        break;
                case 4:
-                       if (NDS_MEMORY_ACC_BUS == access_channel)
+                       if (NDS_MEMORY_ACC_BUS == core_info[coreid].access_channel)
                                write_mem_func = aice_usb_write_mem_w_bus;
                        else
                                write_mem_func = aice_usb_write_mem_w_dim;
@@ -2857,7 +3272,7 @@ static int aice_usb_write_memory_unit(uint32_t addr, uint32_t size,
                                uint32_t value;
                                memcpy(&value, buffer, sizeof(uint32_t));
 
-                               write_mem_func(addr, value);
+                               write_mem_func(coreid, addr, value);
                                buffer += 4;
                                addr += 4;
                        }
@@ -2867,7 +3282,8 @@ static int aice_usb_write_memory_unit(uint32_t addr, uint32_t size,
        return ERROR_OK;
 }
 
-static int aice_bulk_read_mem(uint32_t addr, uint32_t count, uint8_t *buffer)
+static int aice_bulk_read_mem(uint32_t coreid, uint32_t addr, uint32_t count,
+               uint8_t *buffer)
 {
        uint32_t packet_size;
 
@@ -2876,10 +3292,10 @@ static int aice_bulk_read_mem(uint32_t addr, uint32_t count, uint8_t *buffer)
 
                /** set address */
                addr &= 0xFFFFFFFC;
-               if (aice_write_misc(current_target_id, NDS_EDM_MISC_SBAR, addr) != ERROR_OK)
+               if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr) != ERROR_OK)
                        return ERROR_FAIL;
 
-               if (aice_fastread_mem(current_target_id, buffer,
+               if (aice_fastread_mem(coreid, buffer,
                                        packet_size) != ERROR_OK)
                        return ERROR_FAIL;
 
@@ -2891,7 +3307,8 @@ static int aice_bulk_read_mem(uint32_t addr, uint32_t count, uint8_t *buffer)
        return ERROR_OK;
 }
 
-static int aice_bulk_write_mem(uint32_t addr, uint32_t count, const uint8_t *buffer)
+static int aice_bulk_write_mem(uint32_t coreid, uint32_t addr, uint32_t count,
+               const uint8_t *buffer)
 {
        uint32_t packet_size;
 
@@ -2900,10 +3317,10 @@ static int aice_bulk_write_mem(uint32_t addr, uint32_t count, const uint8_t *buf
 
                /** set address */
                addr &= 0xFFFFFFFC;
-               if (aice_write_misc(current_target_id, NDS_EDM_MISC_SBAR, addr | 1) != ERROR_OK)
+               if (aice_write_misc(coreid, NDS_EDM_MISC_SBAR, addr | 1) != ERROR_OK)
                        return ERROR_FAIL;
 
-               if (aice_fastwrite_mem(current_target_id, buffer,
+               if (aice_fastwrite_mem(coreid, buffer,
                                        packet_size) != ERROR_OK)
                        return ERROR_FAIL;
 
@@ -2915,111 +3332,107 @@ static int aice_bulk_write_mem(uint32_t addr, uint32_t count, const uint8_t *buf
        return ERROR_OK;
 }
 
-static int aice_usb_bulk_read_mem(uint32_t addr, uint32_t length, uint8_t *buffer)
+static int aice_usb_bulk_read_mem(uint32_t coreid, uint32_t addr,
+               uint32_t length, uint8_t *buffer)
 {
-       LOG_DEBUG("aice_usb_bulk_read_mem, addr: 0x%08x, length: 0x%08x", addr, length);
+       LOG_DEBUG("aice_usb_bulk_read_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
 
        int retval;
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               aice_usb_set_address_dim(addr);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               aice_usb_set_address_dim(coreid, addr);
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               retval = aice_usb_read_memory_unit(addr, 4, length / 4, buffer);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               retval = aice_usb_read_memory_unit(coreid, addr, 4, length / 4, buffer);
        else
-               retval = aice_bulk_read_mem(addr, length / 4, buffer);
+               retval = aice_bulk_read_mem(coreid, addr, length / 4, buffer);
 
        return retval;
 }
 
-static int aice_usb_bulk_write_mem(uint32_t addr, uint32_t length, const uint8_t *buffer)
+static int aice_usb_bulk_write_mem(uint32_t coreid, uint32_t addr,
+               uint32_t length, const uint8_t *buffer)
 {
-       LOG_DEBUG("aice_usb_bulk_write_mem, addr: 0x%08x, length: 0x%08x", addr, length);
+       LOG_DEBUG("aice_usb_bulk_write_mem, addr: 0x%08" PRIx32 ", length: 0x%08" PRIx32, addr, length);
 
        int retval;
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               aice_usb_set_address_dim(addr);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               aice_usb_set_address_dim(coreid, addr);
 
-       if (NDS_MEMORY_ACC_CPU == access_channel)
-               retval = aice_usb_write_memory_unit(addr, 4, length / 4, buffer);
+       if (NDS_MEMORY_ACC_CPU == core_info[coreid].access_channel)
+               retval = aice_usb_write_memory_unit(coreid, addr, 4, length / 4, buffer);
        else
-               retval = aice_bulk_write_mem(addr, length / 4, buffer);
+               retval = aice_bulk_write_mem(coreid, addr, length / 4, buffer);
 
        return retval;
 }
 
-static int aice_usb_read_debug_reg(uint32_t addr, uint32_t *val)
+static int aice_usb_read_debug_reg(uint32_t coreid, uint32_t addr, uint32_t *val)
 {
-       if (AICE_TARGET_HALTED == core_state) {
+       if (AICE_TARGET_HALTED == core_info[coreid].core_state) {
                if (NDS_EDM_SR_EDMSW == addr) {
-                       *val = edmsw_backup;
+                       *val = core_info[coreid].edmsw_backup;
                } else if (NDS_EDM_SR_EDM_DTR == addr) {
-                       if (target_dtr_valid) {
+                       if (core_info[coreid].target_dtr_valid) {
                                /* if EDM_DTR has read out, clear it. */
-                               *val = target_dtr_backup;
-                               edmsw_backup &= (~0x1);
-                               target_dtr_valid = false;
+                               *val = core_info[coreid].target_dtr_backup;
+                               core_info[coreid].edmsw_backup &= (~0x1);
+                               core_info[coreid].target_dtr_valid = false;
                        } else {
                                *val = 0;
                        }
                }
        }
 
-       return aice_read_edmsr(current_target_id, addr, val);
+       return aice_read_edmsr(coreid, addr, val);
 }
 
-static int aice_usb_write_debug_reg(uint32_t addr, const uint32_t val)
+static int aice_usb_write_debug_reg(uint32_t coreid, uint32_t addr, const uint32_t val)
 {
-       if (AICE_TARGET_HALTED == core_state) {
+       if (AICE_TARGET_HALTED == core_info[coreid].core_state) {
                if (NDS_EDM_SR_EDM_DTR == addr) {
-                       host_dtr_backup = val;
-                       edmsw_backup |= 0x2;
-                       host_dtr_valid = true;
+                       core_info[coreid].host_dtr_backup = val;
+                       core_info[coreid].edmsw_backup |= 0x2;
+                       core_info[coreid].host_dtr_valid = true;
                }
        }
 
-       return aice_write_edmsr(current_target_id, addr, val);
+       return aice_write_edmsr(coreid, addr, val);
 }
 
-static int aice_usb_select_target(uint32_t target_id)
+static int aice_usb_memory_access(uint32_t coreid, enum nds_memory_access channel)
 {
-       current_target_id = target_id;
+       LOG_DEBUG("aice_usb_memory_access, access channel: %u", channel);
 
-       return ERROR_OK;
-}
-
-static int aice_usb_memory_access(enum nds_memory_access channel)
-{
-       LOG_DEBUG("aice_usb_memory_access, access channel: %d", channel);
-
-       access_channel = channel;
+       core_info[coreid].access_channel = channel;
 
        return ERROR_OK;
 }
 
-static int aice_usb_memory_mode(enum nds_memory_select mem_select)
+static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_select)
 {
-       if (memory_select == mem_select)
+       if (core_info[coreid].memory_select == mem_select)
                return ERROR_OK;
 
-       LOG_DEBUG("aice_usb_memory_mode, memory select: %d", mem_select);
+       LOG_DEBUG("aice_usb_memory_mode, memory select: %u", mem_select);
 
-       memory_select = mem_select;
+       core_info[coreid].memory_select = mem_select;
 
-       if (NDS_MEMORY_SELECT_AUTO != memory_select)
-               aice_write_misc(current_target_id, NDS_EDM_MISC_ACC_CTL,
-                               memory_select - 1);
+       if (NDS_MEMORY_SELECT_AUTO != core_info[coreid].memory_select)
+               aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
+                               core_info[coreid].memory_select - 1);
        else
-               aice_write_misc(current_target_id, NDS_EDM_MISC_ACC_CTL,
+               aice_write_misc(coreid, NDS_EDM_MISC_ACC_CTL,
                                NDS_MEMORY_SELECT_MEM - 1);
 
        return ERROR_OK;
 }
 
-static int aice_usb_read_tlb(uint32_t virtual_address, uint32_t *physical_address)
+static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address,
+               target_addr_t *physical_address)
 {
-       LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08x", virtual_address);
+       LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address);
 
        uint32_t instructions[4];
        uint32_t probe_result;
@@ -3029,33 +3442,33 @@ static int aice_usb_read_tlb(uint32_t virtual_address, uint32_t *physical_addres
        uint32_t virtual_offset;
        uint32_t physical_page_number;
 
-       aice_write_dtr(current_target_id, virtual_address);
+       aice_write_dtr(coreid, virtual_address);
 
        /* probe TLB first */
        instructions[0] = MFSR_DTR(R0);
        instructions[1] = TLBOP_TARGET_PROBE(R1, R0);
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
-       aice_read_reg(R1, &probe_result);
+       aice_read_reg(coreid, R1, &probe_result);
 
        if (probe_result & 0x80000000)
                return ERROR_FAIL;
 
        /* read TLB entry */
-       aice_write_dtr(current_target_id, probe_result & 0x7FF);
+       aice_write_dtr(coreid, probe_result & 0x7FF);
 
        /* probe TLB first */
        instructions[0] = MFSR_DTR(R0);
        instructions[1] = TLBOP_TARGET_READ(R0);
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
-       aice_execute_dim(instructions, 4);
+       aice_execute_dim(coreid, instructions, 4);
 
        /* TODO: it should backup mr3, mr4 */
-       aice_read_reg(MR3, &value_mr3);
-       aice_read_reg(MR4, &value_mr4);
+       aice_read_reg(coreid, MR3, &value_mr3);
+       aice_read_reg(coreid, MR4, &value_mr4);
 
        access_page_size = value_mr4 & 0xF;
        if (0 == access_page_size) { /* 4K page */
@@ -3076,56 +3489,60 @@ static int aice_usb_read_tlb(uint32_t virtual_address, uint32_t *physical_addres
        return ERROR_OK;
 }
 
-static int aice_usb_init_cache(void)
+static int aice_usb_init_cache(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_init_cache");
 
        uint32_t value_cr1;
        uint32_t value_cr2;
 
-       aice_read_reg(CR1, &value_cr1);
-       aice_read_reg(CR2, &value_cr2);
-
-       icache.set = value_cr1 & 0x7;
-       icache.log2_set = icache.set + 6;
-       icache.set = 64 << icache.set;
-       icache.way = ((value_cr1 >> 3) & 0x7) + 1;
-       icache.line_size = (value_cr1 >> 6) & 0x7;
-       if (icache.line_size != 0) {
-               icache.log2_line_size = icache.line_size + 2;
-               icache.line_size = 8 << (icache.line_size - 1);
+       aice_read_reg(coreid, CR1, &value_cr1);
+       aice_read_reg(coreid, CR2, &value_cr2);
+
+       struct cache_info *icache = &core_info[coreid].icache;
+
+       icache->set = value_cr1 & 0x7;
+       icache->log2_set = icache->set + 6;
+       icache->set = 64 << icache->set;
+       icache->way = ((value_cr1 >> 3) & 0x7) + 1;
+       icache->line_size = (value_cr1 >> 6) & 0x7;
+       if (icache->line_size != 0) {
+               icache->log2_line_size = icache->line_size + 2;
+               icache->line_size = 8 << (icache->line_size - 1);
        } else {
-               icache.log2_line_size = 0;
-       }
-
-       LOG_DEBUG("\ticache set: %d, way: %d, line size: %d, "
-                       "log2(set): %d, log2(line_size): %d",
-                       icache.set, icache.way, icache.line_size,
-                       icache.log2_set, icache.log2_line_size);
-
-       dcache.set = value_cr2 & 0x7;
-       dcache.log2_set = dcache.set + 6;
-       dcache.set = 64 << dcache.set;
-       dcache.way = ((value_cr2 >> 3) & 0x7) + 1;
-       dcache.line_size = (value_cr2 >> 6) & 0x7;
-       if (dcache.line_size != 0) {
-               dcache.log2_line_size = dcache.line_size + 2;
-               dcache.line_size = 8 << (dcache.line_size - 1);
+               icache->log2_line_size = 0;
+       }
+
+       LOG_DEBUG("\ticache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
+                       "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
+                       icache->set, icache->way, icache->line_size,
+                       icache->log2_set, icache->log2_line_size);
+
+       struct cache_info *dcache = &core_info[coreid].dcache;
+
+       dcache->set = value_cr2 & 0x7;
+       dcache->log2_set = dcache->set + 6;
+       dcache->set = 64 << dcache->set;
+       dcache->way = ((value_cr2 >> 3) & 0x7) + 1;
+       dcache->line_size = (value_cr2 >> 6) & 0x7;
+       if (dcache->line_size != 0) {
+               dcache->log2_line_size = dcache->line_size + 2;
+               dcache->line_size = 8 << (dcache->line_size - 1);
        } else {
-               dcache.log2_line_size = 0;
+               dcache->log2_line_size = 0;
        }
 
-       LOG_DEBUG("\tdcache set: %d, way: %d, line size: %d, "
-                       "log2(set): %d, log2(line_size): %d",
-                       dcache.set, dcache.way, dcache.line_size,
-                       dcache.log2_set, dcache.log2_line_size);
+       LOG_DEBUG("\tdcache set: %" PRIu32 ", way: %" PRIu32 ", line size: %" PRIu32 ", "
+                       "log2(set): %" PRIu32 ", log2(line_size): %" PRIu32 "",
+                       dcache->set, dcache->way, dcache->line_size,
+                       dcache->log2_set, dcache->log2_line_size);
 
-       cache_init = true;
+       core_info[coreid].cache_init = true;
 
        return ERROR_OK;
 }
 
-static int aice_usb_dcache_inval_all(void)
+static int aice_usb_dcache_inval_all(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_dcache_inval_all");
 
@@ -3139,15 +3556,17 @@ static int aice_usb_dcache_inval_all(void)
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
 
-       for (set_index = 0; set_index < dcache.set; set_index++) {
-               for (way_index = 0; way_index < dcache.way; way_index++) {
-                       cache_index = (way_index << (dcache.log2_set + dcache.log2_line_size)) |
-                               (set_index << dcache.log2_line_size);
+       struct cache_info *dcache = &core_info[coreid].dcache;
+
+       for (set_index = 0; set_index < dcache->set; set_index++) {
+               for (way_index = 0; way_index < dcache->way; way_index++) {
+                       cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
+                               (set_index << dcache->log2_line_size);
 
-                       if (ERROR_OK != aice_write_dtr(current_target_id, cache_index))
+                       if (ERROR_OK != aice_write_dtr(coreid, cache_index))
                                return ERROR_FAIL;
 
-                       if (ERROR_OK != aice_execute_dim(instructions, 4))
+                       if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
                                return ERROR_FAIL;
                }
        }
@@ -3155,23 +3574,23 @@ static int aice_usb_dcache_inval_all(void)
        return ERROR_OK;
 }
 
-static int aice_usb_dcache_va_inval(uint32_t address)
+static int aice_usb_dcache_va_inval(uint32_t coreid, uint32_t address)
 {
        LOG_DEBUG("aice_usb_dcache_va_inval");
 
        uint32_t instructions[4];
 
-       aice_write_dtr(current_target_id, address);
+       aice_write_dtr(coreid, address);
 
        instructions[0] = MFSR_DTR(R0);
        instructions[1] = L1D_VA_INVAL(R0);
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
 
-       return aice_execute_dim(instructions, 4);
+       return aice_execute_dim(coreid, instructions, 4);
 }
 
-static int aice_usb_dcache_wb_all(void)
+static int aice_usb_dcache_wb_all(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_dcache_wb_all");
 
@@ -3185,15 +3604,17 @@ static int aice_usb_dcache_wb_all(void)
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
 
-       for (set_index = 0; set_index < dcache.set; set_index++) {
-               for (way_index = 0; way_index < dcache.way; way_index++) {
-                       cache_index = (way_index << (dcache.log2_set + dcache.log2_line_size)) |
-                               (set_index << dcache.log2_line_size);
+       struct cache_info *dcache = &core_info[coreid].dcache;
 
-                       if (ERROR_OK != aice_write_dtr(current_target_id, cache_index))
+       for (set_index = 0; set_index < dcache->set; set_index++) {
+               for (way_index = 0; way_index < dcache->way; way_index++) {
+                       cache_index = (way_index << (dcache->log2_set + dcache->log2_line_size)) |
+                               (set_index << dcache->log2_line_size);
+
+                       if (ERROR_OK != aice_write_dtr(coreid, cache_index))
                                return ERROR_FAIL;
 
-                       if (ERROR_OK != aice_execute_dim(instructions, 4))
+                       if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
                                return ERROR_FAIL;
                }
        }
@@ -3201,23 +3622,23 @@ static int aice_usb_dcache_wb_all(void)
        return ERROR_OK;
 }
 
-static int aice_usb_dcache_va_wb(uint32_t address)
+static int aice_usb_dcache_va_wb(uint32_t coreid, uint32_t address)
 {
        LOG_DEBUG("aice_usb_dcache_va_wb");
 
        uint32_t instructions[4];
 
-       aice_write_dtr(current_target_id, address);
+       aice_write_dtr(coreid, address);
 
        instructions[0] = MFSR_DTR(R0);
        instructions[1] = L1D_VA_WB(R0);
        instructions[2] = DSB;
        instructions[3] = BEQ_MINUS_12;
 
-       return aice_execute_dim(instructions, 4);
+       return aice_execute_dim(coreid, instructions, 4);
 }
 
-static int aice_usb_icache_inval_all(void)
+static int aice_usb_icache_inval_all(uint32_t coreid)
 {
        LOG_DEBUG("aice_usb_icache_inval_all");
 
@@ -3231,15 +3652,17 @@ static int aice_usb_icache_inval_all(void)
        instructions[2] = ISB;
        instructions[3] = BEQ_MINUS_12;
 
-       for (set_index = 0; set_index < icache.set; set_index++) {
-               for (way_index = 0; way_index < icache.way; way_index++) {
-                       cache_index = (way_index << (icache.log2_set + icache.log2_line_size)) |
-                               (set_index << icache.log2_line_size);
+       struct cache_info *icache = &core_info[coreid].icache;
+
+       for (set_index = 0; set_index < icache->set; set_index++) {
+               for (way_index = 0; way_index < icache->way; way_index++) {
+                       cache_index = (way_index << (icache->log2_set + icache->log2_line_size)) |
+                               (set_index << icache->log2_line_size);
 
-                       if (ERROR_OK != aice_write_dtr(current_target_id, cache_index))
+                       if (ERROR_OK != aice_write_dtr(coreid, cache_index))
                                return ERROR_FAIL;
 
-                       if (ERROR_OK != aice_execute_dim(instructions, 4))
+                       if (ERROR_OK != aice_execute_dim(coreid, instructions, 4))
                                return ERROR_FAIL;
                }
        }
@@ -3247,49 +3670,49 @@ static int aice_usb_icache_inval_all(void)
        return ERROR_OK;
 }
 
-static int aice_usb_icache_va_inval(uint32_t address)
+static int aice_usb_icache_va_inval(uint32_t coreid, uint32_t address)
 {
        LOG_DEBUG("aice_usb_icache_va_inval");
 
        uint32_t instructions[4];
 
-       aice_write_dtr(current_target_id, address);
+       aice_write_dtr(coreid, address);
 
        instructions[0] = MFSR_DTR(R0);
        instructions[1] = L1I_VA_INVAL(R0);
        instructions[2] = ISB;
        instructions[3] = BEQ_MINUS_12;
 
-       return aice_execute_dim(instructions, 4);
+       return aice_execute_dim(coreid, instructions, 4);
 }
 
-static int aice_usb_cache_ctl(uint32_t subtype, uint32_t address)
+static int aice_usb_cache_ctl(uint32_t coreid, uint32_t subtype, uint32_t address)
 {
        LOG_DEBUG("aice_usb_cache_ctl");
 
        int result;
 
-       if (cache_init == false)
-               aice_usb_init_cache();
+       if (core_info[coreid].cache_init == false)
+               aice_usb_init_cache(coreid);
 
        switch (subtype) {
                case AICE_CACHE_CTL_L1D_INVALALL:
-                       result = aice_usb_dcache_inval_all();
+                       result = aice_usb_dcache_inval_all(coreid);
                        break;
                case AICE_CACHE_CTL_L1D_VA_INVAL:
-                       result = aice_usb_dcache_va_inval(address);
+                       result = aice_usb_dcache_va_inval(coreid, address);
                        break;
                case AICE_CACHE_CTL_L1D_WBALL:
-                       result = aice_usb_dcache_wb_all();
+                       result = aice_usb_dcache_wb_all(coreid);
                        break;
                case AICE_CACHE_CTL_L1D_VA_WB:
-                       result = aice_usb_dcache_va_wb(address);
+                       result = aice_usb_dcache_va_wb(coreid, address);
                        break;
                case AICE_CACHE_CTL_L1I_INVALALL:
-                       result = aice_usb_icache_inval_all();
+                       result = aice_usb_icache_inval_all(coreid);
                        break;
                case AICE_CACHE_CTL_L1I_VA_INVAL:
-                       result = aice_usb_icache_va_inval(address);
+                       result = aice_usb_icache_va_inval(coreid, address);
                        break;
                default:
                        result = ERROR_FAIL;
@@ -3305,7 +3728,7 @@ static int aice_usb_set_retry_times(uint32_t a_retry_times)
        return ERROR_OK;
 }
 
-static int aice_usb_program_edm(char *command_sequence)
+static int aice_usb_program_edm(uint32_t coreid, char *command_sequence)
 {
        char *command_str;
        char *reg_name_0;
@@ -3337,14 +3760,14 @@ static int aice_usb_program_edm(char *command_sequence)
                        if (reg_name_0 != NULL) {
                                data_value = strtoul(reg_name_0 + 9, NULL, 0);
 
-                               if (aice_write_misc(current_target_id,
+                               if (aice_write_misc(coreid,
                                                        NDS_EDM_MISC_GEN_PORT0, data_value) != ERROR_OK)
                                        return ERROR_FAIL;
 
                        } else if (reg_name_1 != NULL) {
                                data_value = strtoul(reg_name_1 + 9, NULL, 0);
 
-                               if (aice_write_misc(current_target_id,
+                               if (aice_write_misc(coreid,
                                                        NDS_EDM_MISC_GEN_PORT1, data_value) != ERROR_OK)
                                        return ERROR_FAIL;
                        } else {
@@ -3362,19 +3785,26 @@ static int aice_usb_program_edm(char *command_sequence)
        return ERROR_OK;
 }
 
-static int aice_usb_pack_command(bool enable_pack_command)
+static int aice_usb_set_command_mode(enum aice_command_mode command_mode)
 {
-       if (enable_pack_command == false) {
-               /* turn off usb_pack_command, flush usb_packets_buffer */
-               aice_usb_packet_flush();
+       int retval = ERROR_OK;
+
+       /* flush usb_packets_buffer as users change mode */
+       retval = aice_usb_packet_flush();
+
+       if (AICE_COMMAND_MODE_BATCH == command_mode) {
+               /* reset batch buffer */
+               aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+               retval = aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CMD_BUF0_CTRL, 0x40000);
        }
 
-       usb_pack_command = enable_pack_command;
+       aice_command_mode = command_mode;
 
-       return ERROR_OK;
+       return retval;
 }
 
-static int aice_usb_execute(uint32_t *instructions, uint32_t instruction_num)
+static int aice_usb_execute(uint32_t coreid, uint32_t *instructions,
+               uint32_t instruction_num)
 {
        uint32_t i, j;
        uint8_t current_instruction_num;
@@ -3382,7 +3812,7 @@ static int aice_usb_execute(uint32_t *instructions, uint32_t instruction_num)
 
        /* To execute 4 instructions as a special case */
        if (instruction_num == 4)
-               return aice_execute_dim(instructions, 4);
+               return aice_execute_dim(coreid, instructions, 4);
 
        for (i = 0 ; i < instruction_num ; i += 3) {
                if (instruction_num - i < 3) {
@@ -3397,25 +3827,25 @@ static int aice_usb_execute(uint32_t *instructions, uint32_t instruction_num)
                                current_instruction_num * sizeof(uint32_t));
 
                /** fill DIM */
-               if (aice_write_dim(current_target_id,
+               if (aice_write_dim(coreid,
                                        dim_instructions,
                                        4) != ERROR_OK)
                        return ERROR_FAIL;
 
                /** clear DBGER.DPED */
-               if (aice_write_misc(current_target_id,
+               if (aice_write_misc(coreid,
                                        NDS_EDM_MISC_DBGER, NDS_DBGER_DPED) != ERROR_OK)
                        return ERROR_FAIL;
 
                /** execute DIM */
-               if (aice_do_execute(current_target_id) != ERROR_OK)
+               if (aice_do_execute(coreid) != ERROR_OK)
                        return ERROR_FAIL;
 
                /** check DBGER.DPED */
-               if (aice_check_dbger(NDS_DBGER_DPED) != ERROR_OK) {
+               if (aice_check_dbger(coreid, NDS_DBGER_DPED) != ERROR_OK) {
 
                        LOG_ERROR("<-- TARGET ERROR! Debug operations do not finish properly:"
-                                       "0x%08x 0x%08x 0x%08x 0x%08x. -->",
+                                       "0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 " 0x%08" PRIx32 ". -->",
                                        dim_instructions[0],
                                        dim_instructions[1],
                                        dim_instructions[2],
@@ -3455,13 +3885,176 @@ static int aice_usb_set_count_to_check_dbger(uint32_t count_to_check)
        return ERROR_OK;
 }
 
-static int aice_usb_set_data_endian(enum aice_target_endian target_data_endian)
+static int aice_usb_set_data_endian(uint32_t coreid,
+               enum aice_target_endian target_data_endian)
 {
        data_endian = target_data_endian;
 
        return ERROR_OK;
 }
 
+static int fill_profiling_batch_commands(uint32_t coreid, uint32_t reg_no)
+{
+       uint32_t dim_instructions[4];
+
+       aice_usb_set_command_mode(AICE_COMMAND_MODE_BATCH);
+
+       /* halt */
+       if (aice_write_misc(coreid, NDS_EDM_MISC_EDM_CMDR, 0) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* backup $r0 */
+       dim_instructions[0] = MTSR_DTR(0);
+       dim_instructions[1] = DSB;
+       dim_instructions[2] = NOP;
+       dim_instructions[3] = BEQ_MINUS_12;
+       if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+       aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
+
+       /* get samples */
+       if (NDS32_REG_TYPE_GPR == nds32_reg_type(reg_no)) {
+               /* general registers */
+               dim_instructions[0] = MTSR_DTR(reg_no);
+               dim_instructions[1] = DSB;
+               dim_instructions[2] = NOP;
+               dim_instructions[3] = BEQ_MINUS_12;
+       } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(reg_no)) {
+               /* user special registers */
+               dim_instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(reg_no));
+               dim_instructions[1] = MTSR_DTR(0);
+               dim_instructions[2] = DSB;
+               dim_instructions[3] = BEQ_MINUS_12;
+       } else { /* system registers */
+               dim_instructions[0] = MFSR(0, nds32_reg_sr_index(reg_no));
+               dim_instructions[1] = MTSR_DTR(0);
+               dim_instructions[2] = DSB;
+               dim_instructions[3] = BEQ_MINUS_12;
+       }
+       if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+       aice_read_dtr_to_buffer(coreid, AICE_BATCH_DATA_BUFFER_1);
+
+       /* restore $r0 */
+       aice_write_dtr_from_buffer(coreid, AICE_BATCH_DATA_BUFFER_0);
+       dim_instructions[0] = MFSR_DTR(0);
+       dim_instructions[1] = DSB;
+       dim_instructions[2] = NOP;
+       dim_instructions[3] = IRET;  /* free run */
+       if (aice_write_dim(coreid, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+
+       /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
+       if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
+                               usb_out_packets_buffer,
+                               (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       usb_out_packets_buffer_length = 0;
+       usb_in_packets_buffer_length = 0;
+
+       return ERROR_OK;
+}
+
+static int aice_usb_profiling(uint32_t coreid, uint32_t interval, uint32_t iteration,
+               uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
+{
+       uint32_t iteration_count;
+       uint32_t this_iteration;
+       int retval = ERROR_OK;
+       const uint32_t MAX_ITERATION = 250;
+
+       *num_samples = 0;
+
+       /* init DIM size */
+       if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DIM_SIZE, 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* Use AICE_BATCH_DATA_BUFFER_0 to read/write $DTR.
+        * Set it to circular buffer */
+       if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL, 0xC0000) != ERROR_OK)
+               return ERROR_FAIL;
+
+       fill_profiling_batch_commands(coreid, reg_no);
+
+       iteration_count = 0;
+       while (iteration_count < iteration) {
+               if (iteration - iteration_count < MAX_ITERATION)
+                       this_iteration = iteration - iteration_count;
+               else
+                       this_iteration = MAX_ITERATION;
+
+               /* set number of iterations */
+               uint32_t val_iteration;
+               val_iteration = interval << 16 | this_iteration;
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_ITERATION,
+                                       val_iteration) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               /* init AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL to store $PC */
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL,
+                                       0x40000) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               aice_usb_run(coreid);
+
+               /* enable BATCH command */
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL,
+                                       0x80000000) != ERROR_OK) {
+                       aice_usb_halt(coreid);
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               /* wait a while (AICE bug, workaround) */
+               alive_sleep(this_iteration);
+
+               /* check status */
+               uint32_t i;
+               uint32_t batch_status;
+
+               i = 0;
+               while (1) {
+                       aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+
+                       if (batch_status & 0x1) {
+                               break;
+                       } else if (batch_status & 0xE) {
+                               aice_usb_halt(coreid);
+                               retval = ERROR_FAIL;
+                               goto end_profiling;
+                       }
+
+                       if ((i % 30) == 0)
+                               keep_alive();
+
+                       i++;
+               }
+
+               aice_usb_halt(coreid);
+
+               /* get samples from batch data buffer */
+               if (aice_batch_buffer_read(AICE_BATCH_DATA_BUFFER_1,
+                                       samples + iteration_count, this_iteration) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               iteration_count += this_iteration;
+       }
+
+end_profiling:
+       *num_samples = iteration_count;
+
+       return retval;
+}
+
 /** */
 struct aice_port_api_s aice_usb_api = {
        /** */
@@ -3505,8 +4098,6 @@ struct aice_port_api_s aice_usb_api = {
        /** */
        .set_jtag_clock = aice_usb_set_jtag_clock,
        /** */
-       .select_target = aice_usb_select_target,
-       /** */
        .memory_access = aice_usb_memory_access,
        /** */
        .memory_mode = aice_usb_memory_mode,
@@ -3519,7 +4110,7 @@ struct aice_port_api_s aice_usb_api = {
        /** */
        .program_edm = aice_usb_program_edm,
        /** */
-       .pack_command = aice_usb_pack_command,
+       .set_command_mode = aice_usb_set_command_mode,
        /** */
        .execute = aice_usb_execute,
        /** */
@@ -3532,4 +4123,6 @@ struct aice_port_api_s aice_usb_api = {
        .set_count_to_check_dbger = aice_usb_set_count_to_check_dbger,
        /** */
        .set_data_endian = aice_usb_set_data_endian,
+       /** */
+       .profiling = aice_usb_profiling,
 };

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)