/* 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;
}
}