On 02/04/2010 12:11 PM, Jie Zhang wrote:
On 02/04/2010 04:44 AM, Arnim Laeuger wrote:

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).

Haven't had a chance to look at the code yet. What is the mechanism
behind compacting clocks? With the current code, URJ_TAP_CABLE_CLOCK
would stuff (compact?) n requested clocks into a sequence of FT2232
commands, each one clocking 7 times. In which spot did you find further
optimization potential?

I don't see code in current svn to "stuff n requested clocks into a
sequence of FT2232 commands, each one clocking 7 times." Or I might have
missed something.

The attached patch dumps ft2232 commands. With this patch applied, you
can see the ft2232 commands which will be sent out.

Let me use a concrete example to explain what the optimization does.
Without this optimization, you can see the following command sequence:

0x4b 0x01 0x7f 0x4b 0x00 0x00 0x4b 0x00 0x00

With this optimization, it will be optimized to one command:

0x4b 0x03 0x03

Another more interesting example is it will optimize

0x4b 0x00 0x7f 0x4b 0x00 0x7f 0x4b 0x00 0x00 0x4b 0x01 0x7f
0x4b 0x00 0x00 0x4b 0x00 0x00

into

0x4b 0x06 0x1b

This patch gives us amazing performance improvement when loading program
into memory via gdbproxy. I don't have exact number for improvement now
for current UrJTAG. The old number was about 50% increase on throughput
IIRC.

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?

post_signals was added in this change:

Revision 1419 - (view) (download) (annotate) - [select for diffs]
Modified Mon Jan 19 12:06:06 2009 UTC (12 months, 2 weeks ago) by kawk

[2187351] Direct JTAG signal access, get/set_trst extension integrated
from getset_pod branch

My understanding is that post_signals acts as a "notepad" to track the
status of the pod signals for the queued actions. This allows to predict
the status of pod signals without having the need to read them from the
FT2232.

Thanks for explanation. So I think what I need to do is to set
post_signals to what the signals should be after
URJ_TAP_CABLE_CLOCK_COMPACT is done. Right?

I attached a new version of the patch, which sets post_signals to what the signals should be after URJ_TAP_CABLE_CLOCK_COMPACT is done.

This new version also change the name of ft2232_clock_schedule_compact to ft2232_clock_compact_schedule. Test result seems good. Linux kernel loading speed improvement ranges from 17% to 47% depending on the cable settings.

Any comments?


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_compact_schedule): New.
    (ft2232_flush): Compact consecutive clocks.


Index: include/urjtag/cable.h
===================================================================
--- include/urjtag/cable.h	(revision 1758)
+++ 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 1758)
+++ 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 1759)
+++ src/tap/cable/ft2232.c	(working copy)
@@ -1255,6 +1255,22 @@ ft2232_clock_schedule (urj_cable_t *cabl
 
 
 static void
+ft2232_clock_compact_schedule (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;
@@ -1627,6 +1643,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++)
         {
@@ -1634,12 +1656,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_compact_schedule (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_compact_schedule (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)
@@ -1697,6 +1775,20 @@ ft2232_flush (urj_cable_t *cable, urj_ca
                     params->last_tdo_valid = last_tdo_valid_finish = 0;
                     break;
                 }
+            case URJ_TAP_CABLE_CLOCK_COMPACT:
+                {
+                    post_signals &=
+                        ~(URJ_POD_CS_TCK | URJ_POD_CS_TDI | URJ_POD_CS_TMS);
+                    post_signals |=
+                        ((cable->todo.data[j].arg.clock.
+                          tms >> cable->todo.data[j].arg.clock.
+                          n) ? URJ_POD_CS_TMS : 0);
+                    post_signals |=
+                        (cable->todo.data[j].arg.clock.
+                         tdi ? URJ_POD_CS_TDI : 0);
+                    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