This patch tries to optimize TMS clocks by compacting multiple clocks into one FT2232 command. This gives us 6% flash program time reduction. And it gives us more performance improvement for gdbproxy when loading program via our gnICE and gnICE+ cables. I think this will help other JTAG cables based on FT2232(H).

But there is one problem I don't know the resolution. What is post_signals in ft2232.c for? How should I set it for URJ_TAP_CABLE_CLOCK_COMPACT?

And any comments?


Thanks,
Jie
  * include/urjtag/cable.h (enum action): Add URJ_TAP_CABLE_CLOCK_COMPACT.
  * src/tap/cable/generic.c (do_one_queued_action): Handle
    URJ_TAP_CABLE_CLOCK_COMPACT to turn off GCC warning.
  * src/tap/cable/ft2232.c (ft2232_clock_schedule_compact): New.
    (ft2232_flush): Compact consecutive clocks.


Index: include/urjtag/cable.h
===================================================================
--- include/urjtag/cable.h	(revision 1754)
+++ include/urjtag/cable.h	(working copy)
@@ -102,6 +102,7 @@ struct URJ_CABLE_QUEUE
     enum
     {
         URJ_TAP_CABLE_CLOCK,
+        URJ_TAP_CABLE_CLOCK_COMPACT,
         URJ_TAP_CABLE_GET_TDO,
         URJ_TAP_CABLE_TRANSFER,
         URJ_TAP_CABLE_SET_SIGNAL,
Index: src/tap/cable/generic.c
===================================================================
--- src/tap/cable/generic.c	(revision 1754)
+++ src/tap/cable/generic.c	(working copy)
@@ -177,6 +177,8 @@ do_one_queued_action (urj_cable_t *cable
                 cable->driver->get_signal (cable,
                                            cable->todo.data[i].arg.value.sig);
             break;
+        case URJ_TAP_CABLE_CLOCK_COMPACT: /* Turn off GCC warning */
+            break;
         }
         urj_log (URJ_LOG_LEVEL_DETAIL, "do_one_queued done\n");
 
Index: src/tap/cable/ft2232.c
===================================================================
--- src/tap/cable/ft2232.c	(revision 1754)
+++ src/tap/cable/ft2232.c	(working copy)
@@ -1247,6 +1247,22 @@ ft2232_clock_schedule (urj_cable_t *cabl
 
 
 static void
+ft2232_clock_schedule_compact (urj_cable_t *cable, int length, uint8_t byte)
+{
+    params_t *params = (params_t *)cable->params;
+    urj_tap_cable_cx_cmd_root_t *cmd_root = &(params->cmd_root);
+
+    urj_tap_cable_cx_cmd_queue (cmd_root, 0);
+    /* Clock Data to TMS/CS Pin (no Read) */
+    urj_tap_cable_cx_cmd_push (cmd_root, MPSSE_WRITE_TMS |
+                               MPSSE_LSB | MPSSE_BITMODE |
+                               MPSSE_WRITE_NEG );
+    urj_tap_cable_cx_cmd_push (cmd_root, length);
+    urj_tap_cable_cx_cmd_push (cmd_root, byte);
+}
+
+
+static void
 ft2232_clock (urj_cable_t *cable, int tms, int tdi, int n)
 {
     params_t *params = (params_t *) cable->params;
@@ -1619,6 +1635,12 @@ ft2232_flush (urj_cable_t *cable, urj_ca
         int last_tdo_valid_schedule = params->last_tdo_valid;
         int last_tdo_valid_finish = params->last_tdo_valid;
 
+        if (cable->todo.num_items == 1
+            && cable->todo.data[cable->todo.next_item].action
+               == URJ_TAP_CABLE_CLOCK_COMPACT
+            && how_much != URJ_TAP_CABLE_COMPLETELY)
+            break;
+
         for (j = i = cable->todo.next_item, n = 0; n < cable->todo.num_items;
              n++)
         {
@@ -1626,12 +1648,68 @@ ft2232_flush (urj_cable_t *cable, urj_ca
             switch (cable->todo.data[i].action)
             {
             case URJ_TAP_CABLE_CLOCK:
-                ft2232_clock_schedule (cable,
-                                       cable->todo.data[i].arg.clock.tms,
-                                       cable->todo.data[i].arg.clock.tdi,
-                                       cable->todo.data[i].arg.clock.n);
-                last_tdo_valid_schedule = 0;
-                break;
+            case URJ_TAP_CABLE_CLOCK_COMPACT:
+                {
+                    int tdi = cable->todo.data[i].arg.clock.tdi ? 1 << 7 : 0;
+                    int length = 0;
+                    uint8_t byte = 0;
+                    int tms = 0;
+                    int cn = 0;
+
+                    if (cable->todo.data[i].action == URJ_TAP_CABLE_CLOCK_COMPACT)
+                    {
+                        length = cable->todo.data[i].arg.clock.n;
+                        byte = cable->todo.data[i].arg.clock.tms;
+                    }
+
+                  more_cable_clock:
+
+                    if (cable->todo.data[i].action == URJ_TAP_CABLE_CLOCK)
+                    {
+                        tms = cable->todo.data[i].arg.clock.tms ? 1 : 0;
+                        cn = cable->todo.data[i].arg.clock.n;
+                    }
+                    while (cn > 0)
+                    {
+                        byte |= tms << length;
+                        cn--;
+                        length++;
+                        if (length == 7)
+                        {
+                            ft2232_clock_schedule_compact (cable, 6, byte | tdi);
+                            length = 0;
+                            byte = 0;
+                        }
+                    }
+                    if (n + 1 < cable->todo.num_items
+                        && cable->todo.data[(i + 1) % cable->todo.max_items].action == URJ_TAP_CABLE_CLOCK
+                        && (cable->todo.data[(i + 1) % cable->todo.max_items].arg.clock.tdi ? 1 << 7 : 0) == tdi)
+                    {
+                        i++;
+                        if (i >= cable->todo.max_items)
+                            i = 0;
+                        n++;
+                        goto more_cable_clock;
+                    }
+                    if (length)
+                    {
+                        if (n + 1 < cable->todo.num_items
+                            || how_much == URJ_TAP_CABLE_COMPLETELY)
+                            ft2232_clock_schedule_compact (cable, length - 1, byte | tdi);
+                        else
+                        {
+                            cable->todo.data[i].action = URJ_TAP_CABLE_CLOCK_COMPACT;
+                            cable->todo.data[i].arg.clock.tms = byte;
+                            cable->todo.data[i].arg.clock.n = length;
+                            i--;
+                            if (i == -1)
+                                i = cable->todo.max_items;
+                        }
+                    }
+
+                    last_tdo_valid_schedule = 0;
+                    break;
+                }
 
             case URJ_TAP_CABLE_GET_TDO:
                 if (!last_tdo_valid_schedule)
@@ -1689,6 +1767,11 @@ ft2232_flush (urj_cable_t *cable, urj_ca
                     params->last_tdo_valid = last_tdo_valid_finish = 0;
                     break;
                 }
+            case URJ_TAP_CABLE_CLOCK_COMPACT:
+                {
+                    params->last_tdo_valid = last_tdo_valid_finish = 0;
+                    break;
+                }
             case URJ_TAP_CABLE_GET_TDO:
                 {
                     int tdo;
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
UrJTAG-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to