/* ds_ts_sdwrr.asl -- scheduling script for DiffServ example */ /* * Smoothed Weighted Deficit Round Robin scheduler */ #include "tsNp5.h" /* * Typical limits assignment: * Quantum = max_PDU_size/3 * limit1 = queue_weight x Quantum * limit2 = queue_weight x Quantum x 2 * limit3 = queue_weight x Quantum x 3 */ unsigned limit1 param_block_inout_extended [0:3]; unsigned limit2 param_block_inout_extended [4:7]; unsigned limit3 param_block_inout_extended [8:11]; unsigned expense param_block_inout_extended [12:15]; unsigned(4) updated_expense; unsigned(1) FIFO_advance; /* * Maximal rate is used to penalize oversubscribed queues with * shared dynamic scheduler. Rates are measured in block times. */ unsigned max_rate param_block_inout_extended [16:17]; unsigned average_rate param_block_inout_extended [18:19]; unsigned last_sched_time param_block_inout_extended [20:23]; script sdwrr { if (is_first) { /* average_rate= 1/8 (current_rate-average_rate) + average rate */ average_rate = average_rate + ((current_time - last_sched_time)>>3) - (average_rate>>3); /* update scheduling timestamp */ last_sched_time = current_time + pdu_ttt; /* * see if the queue had just entered busy period, * in which case initialize expense to 0 */ if (is_Q_new_to_FIFO) expense = 0; /* calculate new expense */ updated_expense = expense + pdu_length; /* calculate how many FIFO lists this queue should advance */ FIFO_advance = 0; expense = updated_expense; if (updated_expense > limit1) { FIFO_advance = 1; expense = updated_expense - limit1; } if (updated_expense > limit2) { FIFO_advance = 2; expense = updated_expense - limit2; } if ( updated_expense > limit3) { FIFO_advance = 3; expense = updated_expense - limit3; } /* * calculate next FIFO list for current queue: * current = (current + advance) mod 4 */ queue_currentlist = (queue_currentlist + FIFO_advance) & 0x3; /* * if maximum rate exceeded, send queue to * shared dynamic rescheduler */ if (average_rate < max_rate ) { send_Q_to_dynamic_rescheduler=true; pdu_interval = max_rate + pdu_ttt; upd_interval = true; } /* * Go to the next FIFO list and update enqueuing list. * Parameter FIFO_sched_next_currentlist is set only by the hardware * as follows: Bits 0:1 are set to the next FIFO list, which is the * same as current one if there is still a non-empty queue on the * current one, or is set to the next non-empty FIFO list otherwise. * Bits 4:5 are set to (bits 0:1 + 1 ) mod 4 * Here we leave bits 0:1 as is, and increment bits 4:5 by 2 mod 4, * so that enqueuing list is (current list + 3) mod 4 */ FIFO_sched_currentlist = (FIFO_sched_next_currentlist+0x20)&0x3f; } }