More lightweight TCP server implementation/library? Topic is solved

Technical questions regarding the XTC tools and programming with XMOS.
mozcelikors
Experienced Member
Posts: 75
Joined: Sat May 07, 2016 11:47 am

More lightweight TCP server implementation/library?

Post by mozcelikors »

Hello guys,

I need to make room for a core in tile[1] in order to monitor the cores, but ethernet library Im using rgmii implementation uses all 8 cores of the tile[1] already. There are a loot of par statements here. How can we reduce this? or is there more lightweight implementation? Thanks in advance.

Code: Select all

void rgmii_ethernet_mac(server ethernet_rx_if i_rx_lp[n_rx_lp], static const unsigned n_rx_lp,
                        server ethernet_tx_if i_tx_lp[n_tx_lp], static const unsigned n_tx_lp,
                        streaming chanend ? c_rx_hp,
                        streaming chanend ? c_tx_hp,
                        streaming chanend c_rgmii_cfg,
                        rgmii_ports_t &rgmii_ports,
                        enum ethernet_enable_shaper_t enable_shaper)
{
  rx_client_state_t rx_client_state_lp[n_rx_lp];
  tx_client_state_t tx_client_state_lp[n_tx_lp];

  if (!ETHERNET_SUPPORT_HP_QUEUES && (!isnull(c_rx_hp) || !isnull(c_tx_hp))) {
    fail("Using high priority channels without #define ETHERNET_SUPPORT_HP_QUEUES set true");
  }

  init_rx_client_state(rx_client_state_lp, n_rx_lp);
  init_tx_client_state(tx_client_state_lp, n_tx_lp);

  mii_macaddr_hash_table_init();

  mii_init_lock();

  unsafe {
    unsigned int buffer_rx[RGMII_MAC_BUFFER_COUNT_RX * sizeof(mii_packet_t) / 4];
    unsigned int buffer_free_pointers_rx[RGMII_MAC_BUFFER_COUNT_RX];
    unsigned int buffer_used_pointers_rx_lp[RGMII_MAC_BUFFER_COUNT_RX + 1];
    unsigned int buffer_used_pointers_rx_hp[RGMII_MAC_BUFFER_COUNT_RX + 1];
    buffers_free_t free_buffers_rx;
    buffers_used_t used_buffers_rx_lp;
    buffers_used_t used_buffers_rx_hp;

    unsigned int buffer_tx_lp[RGMII_MAC_BUFFER_COUNT_TX * sizeof(mii_packet_t) / 4];
    unsigned int buffer_tx_hp[RGMII_MAC_BUFFER_COUNT_TX * sizeof(mii_packet_t) / 4];
    unsigned int buffer_free_pointers_tx_lp[RGMII_MAC_BUFFER_COUNT_TX];
    unsigned int buffer_free_pointers_tx_hp[RGMII_MAC_BUFFER_COUNT_TX];
    unsigned int buffer_used_pointers_tx_lp[RGMII_MAC_BUFFER_COUNT_TX + 1];
    unsigned int buffer_used_pointers_tx_hp[RGMII_MAC_BUFFER_COUNT_TX + 1];
    buffers_free_t free_buffers_tx_lp;
    buffers_free_t free_buffers_tx_hp;
    buffers_used_t used_buffers_tx_lp;
    buffers_used_t used_buffers_tx_hp;

    // Create unsafe pointers to pass to two parallel tasks
    buffers_used_t * unsafe p_used_buffers_rx_lp = &used_buffers_rx_lp;
    buffers_used_t * unsafe p_used_buffers_rx_hp = &used_buffers_rx_hp;
    buffers_free_t * unsafe p_free_buffers_rx = &free_buffers_rx;
    in buffered port:32 * unsafe p_rxd_1000_unsafe = &rgmii_ports.p_rxd_1000;
    in port * unsafe p_rxdv_unsafe = &rgmii_ports.p_rxdv;
    in buffered port:1 * unsafe p_rxer_unsafe = &rgmii_ports.p_rxer;
    rx_client_state_t * unsafe p_rx_client_state_lp =
      (rx_client_state_t * unsafe)&rx_client_state_lp[0];

    streaming chan c_rx_to_manager[2], c_manager_to_tx, c_ping_pong;
    streaming chanend * unsafe c_speed_change;
    int speed_change_ids[6];
    rgmii_inband_status_t current_mode = INITIAL_MODE;

    rgmii_configure_ports(rgmii_ports.p_rxclk, rgmii_ports.p_rxer, rgmii_ports.p_rxd_1000, rgmii_ports.p_rxd_10_100,
                          rgmii_ports.p_rxd_interframe, rgmii_ports.p_rxdv, rgmii_ports.p_rxdv_interframe,
                          rgmii_ports.p_txclk_in, rgmii_ports.p_txclk_out, rgmii_ports.p_txer, rgmii_ports.p_txen, rgmii_ports.p_txd,
                          rgmii_ports.rxclk, rgmii_ports.rxclk_interframe, rgmii_ports.txclk, rgmii_ports.txclk_out);

    log_speed_change_pointers(speed_change_ids);
    c_speed_change = (streaming chanend * unsafe)speed_change_ids;

    ethernet_port_state_t port_state;
    init_server_port_state(port_state, enable_shaper == ETHERNET_ENABLE_SHAPER);

    ethernet_port_state_t * unsafe p_port_state = (ethernet_port_state_t * unsafe)&port_state;

    while(1)
    {
      // Setup the buffer pointers
      buffers_used_initialize(used_buffers_rx_lp, buffer_used_pointers_rx_lp);
      buffers_used_initialize(used_buffers_rx_hp, buffer_used_pointers_rx_hp);
      buffers_free_initialize(free_buffers_rx, (unsigned char*)buffer_rx,
                              buffer_free_pointers_rx, RGMII_MAC_BUFFER_COUNT_RX);

      buffers_used_initialize(used_buffers_tx_lp, buffer_used_pointers_tx_lp);
      buffers_used_initialize(used_buffers_tx_hp, buffer_used_pointers_tx_hp);
      buffers_free_initialize(free_buffers_tx_lp, (unsigned char*)buffer_tx_lp,
                              buffer_free_pointers_tx_lp, RGMII_MAC_BUFFER_COUNT_TX);
      buffers_free_initialize(free_buffers_tx_hp, (unsigned char*)buffer_tx_hp,
                              buffer_free_pointers_tx_hp, RGMII_MAC_BUFFER_COUNT_TX);

      if (current_mode == INBAND_STATUS_100M_FULLDUPLEX_UP ||
          current_mode == INBAND_STATUS_100M_FULLDUPLEX_DOWN ||
          current_mode == INBAND_STATUS_10M_FULLDUPLEX_UP ||
          current_mode == INBAND_STATUS_10M_FULLDUPLEX_DOWN)
      {
        mii_macaddr_set_num_active_filters(1);

        par
        {
          {
            rgmii_10_100_master_tx_pins(c_manager_to_tx, rgmii_ports.p_txd, c_speed_change[0]);
            empty_channel(c_manager_to_tx);
          }

          {
            clearbuf(rgmii_ports.p_rxd_10_100);
            par {
              {
                rgmii_10_100_master_rx_pins(c_rx_to_manager[0], rgmii_ports.p_rxd_10_100, rgmii_ports.p_rxdv,
                                            rgmii_ports.p_rxer, c_speed_change[1]);
                empty_channel(c_rx_to_manager[0]);
              }
              {
                rgmii_buffer_manager(c_rx_to_manager[0], c_speed_change[3],
                                     *p_used_buffers_rx_lp, *p_used_buffers_rx_hp, *p_free_buffers_rx, 0);
              }
              {
                // Just wait for a change from 100Mb mode and empty those channels
                c_speed_change[2] :> unsigned tmp;
                c_speed_change[4] :> unsigned tmp;
              }
            }
          }

          {
            rgmii_ethernet_rx_server((rx_client_state_t *)p_rx_client_state_lp, i_rx_lp, n_rx_lp,
                                     c_rx_hp, c_rgmii_cfg, rgmii_ports.p_txclk_out, rgmii_ports.p_rxd_interframe,
                                     *p_used_buffers_rx_lp, *p_used_buffers_rx_hp,
                                     *p_free_buffers_rx, current_mode, speed_change_ids, p_port_state);
          }

          {
            rgmii_ethernet_tx_server(tx_client_state_lp, i_tx_lp, n_tx_lp,
                                     c_tx_hp,
                                     c_manager_to_tx, c_speed_change[5],
                                     used_buffers_tx_lp, free_buffers_tx_lp,
                                     used_buffers_tx_hp, free_buffers_tx_hp,
                                     p_port_state);
          }
        }
      }
      else
      {
        mii_macaddr_set_num_active_filters(2);

        par
        {
          {
            rgmii_tx_lld(c_manager_to_tx, rgmii_ports.p_txd, c_speed_change[0]);
            empty_channel(c_manager_to_tx);
          }

          {
            clearbuf(*p_rxd_1000_unsafe);
            par {
              {
                rgmii_rx_lld(c_rx_to_manager[0], c_ping_pong, 0, c_speed_change[1],
			                       *p_rxd_1000_unsafe, *p_rxdv_unsafe, *p_rxer_unsafe);
                empty_channel(c_rx_to_manager[0]);
                empty_channel(c_ping_pong);
              }
              {
                rgmii_rx_lld(c_rx_to_manager[1], c_ping_pong, 1, c_speed_change[2],
			                       *p_rxd_1000_unsafe, *p_rxdv_unsafe, *p_rxer_unsafe);
                empty_channel(c_rx_to_manager[1]);
                empty_channel(c_ping_pong);
              }
              {
                rgmii_buffer_manager(c_rx_to_manager[0], c_speed_change[3],
                                     *p_used_buffers_rx_lp, *p_used_buffers_rx_hp, *p_free_buffers_rx, 0);
              }
              {
                rgmii_buffer_manager(c_rx_to_manager[1], c_speed_change[4],
                                     *p_used_buffers_rx_lp, *p_used_buffers_rx_hp, *p_free_buffers_rx, 1);
              }
            }
          }

          {
            rgmii_ethernet_rx_server((rx_client_state_t *)p_rx_client_state_lp, i_rx_lp, n_rx_lp,
                                     c_rx_hp, c_rgmii_cfg,
                                     rgmii_ports.p_txclk_out, rgmii_ports.p_rxd_interframe,
                                     *p_used_buffers_rx_lp, *p_used_buffers_rx_hp,
                                     *p_free_buffers_rx, current_mode, speed_change_ids,
                                     p_port_state);
          }

          {
            rgmii_ethernet_tx_server(tx_client_state_lp, i_tx_lp, n_tx_lp,
                                     c_tx_hp,
                                     c_manager_to_tx, c_speed_change[5],
                                     used_buffers_tx_lp, free_buffers_tx_lp,
                                     used_buffers_tx_hp, free_buffers_tx_hp,
                                     p_port_state);
          }
        }
      }
    }
  }
}
View Solution
DemoniacMilk
XCore Addict
Posts: 191
Joined: Tue Jul 05, 2016 2:19 pm

Post by DemoniacMilk »

Maybe you find some info here:
https://www.xcore.com/forum/viewtopic.p ... it=#p24252

Also note that one of the cores on tile[1] is running the config interface and phy driver only, both combinable threads that should be idle most of the time: the phy driver is simply polling the link state periodically and theconfig interface reacts to events on ethernet_cfg_if.

If you are able to create your thread as a [[combinable]] while(1){ select {..}} statement with only event handling inside) then you can add that thread to the same core.