next up previous contents
Next: Fetch-Einheit Up: VHDL-Quellen Previous: VHDL-Quellen   Inhalt

Scheduler

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
 
entity PriorityManager is
  
  generic (
    parameterBreite     : integer range 1 to 31  := 31;   - Bits fuer Deadline etc.
    totalStackNumber    : integer range 1 to 127 := 4;    - Anzahl der Threads
    ld_totalStackNumber : integer range 1 to 7   := 2);   - Logarithmus Dualis
 
  port (
    clk           : in  std_logic;       - Clock
    reset         : in  std_logic;       - Reset (Aktiv High)
    
    signalArrived : in  std_logic_vector(totalStackNumber-1 downto 0);
                                         - liegt ein Signal an?
    lockNeeded    : in  std_logic_vector(totalStackNumber-1 downto 0);
                                         - Thread wartet auf Spinlock
    swActive      : in  std_logic_vector(totalStackNumber-1 downto 0);
                                         - Software Aktiv
    hwActive      : in  std_logic_vector(totalStackNumber-1 downto 0);
                                         - Hardware Aktiv (Signal)
    opsExecution  : in  std_logic_vector(totalStackNumber-1 downto 0);
                                         - Es wird gerade MikroCode ausgefuehrt
    latency       : in  std_logic_vector(1 downto 0);
                                         - Der letzte Befehl hatte eine Latenz
    fill          : in  std_logic_vector((4*totalStackNumber)-1 downto 0);
                                         - Fuellstand erster Thread
    parameter     : in  std_logic_vector((parameterBreite*totalStackNumber)-1 downto 0);
                                         - Parameter erster Thread
    IdThreadTag   : out std_logic_vector(ld_totalStackNumber-1 downto 0);
                                         - Als naechstes auszufuehren
    IdInvalid     : out std_logic);      - Keiner kann ausgefuehrt werden
 
end PriorityManager;
 
 ------------------------------------
 ------------------------------------
 
architecture FPP_Scheduler of PriorityManager is
 
  subtype param_int   is std_logic_vector(parameterBreite-1 downto 0);
  subtype prio_int    is std_logic_vector(parameterBreite downto 0);
  subtype fi_int      is std_logic_vector(3 downto 0);
  subtype latenz_int  is std_logic_vector(1 downto 0);
  type param_int_arr  is array(0 to totalStackNumber-1) of param_int;
  type prio_int_arr   is array(0 to totalStackNumber-1) of prio_int;
  type fi_int_arr     is array(0 to totalStackNumber-1) of fi_int;
  type latenz_int_arr is array(0 to totalStackNumber-1) of latenz_int;
  type m_arr          is array(0 to totalStackNumber-1) of integer range 0 to totalStackNumber-1;
  signal param         : param_int_arr;          - Parameter array
  signal fi            : fi_int_arr;
 
 
begin   - FPP_Scheduler
  
  g: for i in 0 to totalStackNumber-1 generate
    param(i) <= parameter((parameterBreite*(i+1))-1 downto parameterBreite*i);
    fi(i) <= fill((4*(i+1))-1 downto 4*i); 
  end generate g;
 
  
   - purpose: Berechnet den naechsten auszufuehrenden Thread
   - Der ausfuehrbare Thread mit der hoechsten prioritaet kommt drann
   - type   : sequential
   - inputs : clk, reset, see entity
   - outputs: IdThreadTag, IdInvalid
  p: process (clk, reset)
 
    variable params     : param_int_arr;
    variable priorities : prio_int_arr;   - Temporaere Variablen
    variable k          : integer;
    variable full       : std_logic;
    variable latenzen   : latenz_int_arr;
    variable m          : m_arr;
    variable lastScheduled : integer;
    variable Invalid       : std_logic;
    
  begin   - process p
        
    if reset = '1' then                  - asynchronous reset (active high)
 
      lastScheduled := 0;
      k             := 0;
      IdInvalid     <= '0';
      Invalid       := '0';
      
      for i in 0 to ld_totalStackNumber-1 loop
        IdThreadTag(i) <= '0';
      end loop;
      
      for i in 0 to totalStackNumber-1 loop
        latenzen(i) := conv_std_logic_vector(0,2);
        for j in 0 to parameterBreite-1 loop
          params(i)(j) := '0';
        end loop;
      end loop;
 
    elsif clk'event and clk = '1' then   - rising clock edge
 
      for i in 0 to totalStackNumber-1 loop
        if signalArrived(i) = '1' then
          params(i) := param(i);
        end if;
      end loop;   - i
 
       - Latenzen von der Decode-Stufe
      if Invalid = '0' and latency /= ``00`` then
        latenzen(lastScheduled) := latency;
      end if;
 
      for i in 0 to totalStackNumber-1 loop
        
         - Issue Threshold (>=3)
        if unsigned(fi(i)) < 3 then
          full := '0';
        else
          full := '1';
        end if;
        
        priorities(i)(parameterBreite-1 downto 0) := params(i);
        priorities(i)(parameterBreite) :=     (not (latenzen(i)(0) or latenzen(i)(1))
                                               and hwActive(i) and swActive(i)
                                               and not lockNeeded(i)
                                               and (full or opsExecution(i)));
      end loop;   - i
 
       - den hoechsten suchen
      for i in 0 to totalStackNumber-1 loop
        m(i):= i;
      end loop;
 
       - Der Vergleicherbaum.
      for j in 0 to ld_totalStackNumber-1 loop
        for i in 0 to (totalStackNumber/2**(j+1))-1 loop
          if priorities(m((2*i+1)*2**j))>priorities(m((2*i)*2**j)) then
            m((2*i)*2**j):=m((2*i+1)*2**j);
          end if;
        end loop;
      end loop;
 
      k:=m(0);  
 
       - hoechsten oder invalid an decode weitergeben
      if priorities(k)(parameterBreite) = '1' then
        IdThreadTag   <= conv_std_logic_vector(k,ld_totalStackNumber);
        IdInvalid     <= '0';
        Invalid       := '0';
        lastScheduled := k;
      else
        IdInvalid     <= '1';
        Invalid       := '1';
      end if;
      
       - Latenzen runterzaehlen
      for i in 0 to totalStackNumber-1 loop
        if unsigned(latenzen(i)) /= 0 then
          latenzen(i) := unsigned(latenzen(i)) - 1;
        end if;
      end loop;   - i
 
    end if;
  end process p;
 
end FPP_Scheduler;
 
 ------------------------------------
 ------------------------------------
 
architecture GP_Scheduler of PriorityManager is
 
  subtype param_int   is std_logic_vector(parameterBreite-1 downto 0);
  subtype prio_int    is std_logic_vector(parameterBreite downto 0);
  subtype fi_int      is std_logic_vector(3 downto 0);
  subtype latenz_int  is std_logic_vector(1 downto 0);
  subtype remain_int  is std_logic_vector(parameterBreite-4 downto 0);
  subtype class_int   is std_logic_vector(2 downto 0);
  type param_int_arr  is array(0 to totalStackNumber-1) of param_int;
  type prio_int_arr   is array(0 to totalStackNumber-1) of prio_int;
  type fi_int_arr     is array(0 to totalStackNumber-1) of fi_int;
  type latenz_int_arr is array(0 to totalStackNumber-1) of latenz_int;
  type remain_int_arr is array(0 to totalStackNumber-1) of remain_int;
  type class_int_arr  is array(0 to totalStackNumber-1) of class_int;
  type m_arr          is array(0 to totalStackNumber-1) of integer range 0 to totalStackNumber-1;
  signal param         : param_int_arr;          - Parameter array
  signal fi            : fi_int_arr;
  
 
begin   - GP_Scheduler
  
  g: for i in 0 to totalStackNumber-1 generate
    param(i) <= parameter((parameterBreite*(i+1))-1 downto parameterBreite*i);
    fi(i) <= fill((4*(i+1))-1 downto 4*i); 
  end generate g;
 
  
   - purpose: Berechnet den naechsten auszufuehrenden Thread
   - Die Threads werden in Klassen aufgeteilt:
   -  000 : nicht echtzeifaehig: laeuft, wenn nichts anderes geht.
   -  001 : minimal: Kann mehr bekommen als seinen Anteil
   -  101 : maximal: Kann weniger bekommen als seinen Anteil
   -  110 : exakt:   Muss genau seinen Anteil bekommen
   -  111 : kurz:    Wie exakt, wird aber zuerst bedient.
   - Der ausfuehrbare Thread mit der hoechsten Klasse und darin
   - der hoechsten Resttakte im Intervall kommt dran.
   - ACHTUNG: Da min und ex zunaechst gleichzeitig ausgefuehrt werden,
   - bekommen minimale auch erstmal 110. Erst wenn sie ihren Anteil
   - verbraucht haben, wechseln sie nach 001.
   - type   : sequential
   - inputs : clk, reset, see entity
   - outputs: IdThreadTag, IdInvalid
  p: process (clk, reset)
 
    constant granularity: std_logic_vector(parameterBreite-4 downto 0) := ``1100100``;  - =100
    constant gr         : integer := 99;
    variable params     : param_int_arr;
    variable remain     : remain_int_arr;
    variable klasse     : class_int_arr;
    variable priorities : prio_int_arr;   - Temporaere Variablen
    variable k          : integer;
    variable counter    : integer range 0 to 100;
    variable full       : std_logic;
    variable darf       : std_logic;
    variable latenzen   : latenz_int_arr;
    variable m          : m_arr;
    variable lastScheduled : integer;
    variable Invalid       : std_logic;
  
  begin   - process p
        
    if reset = '1' then                  - asynchronous reset (active high)
 
      lastScheduled := 0;
      k             := 0;
      counter       := 0;
      IdInvalid     <= '0';
      Invalid       := '0';
      for i in 0 to ld_totalStackNumber-1 loop
        IdThreadTag(i)   <= '0';
      end loop;
      for i in 0 to totalStackNumber-1 loop
        latenzen(i) := conv_std_logic_vector(0,2);
        remain(i)   := granularity;
        klasse(i)   := ``000``;
        for j in 0 to parameterBreite-1 loop
          params(i)(j)   := '0';
        end loop;
      end loop;
 
    elsif clk'event and clk = '1' then   - rising clock edge
 
      for i in 0 to totalStackNumber-1 loop
        if signalArrived(i) = '1' then
          params(i) := param(i);
        end if;
      end loop;   - i
      
       - Intervallzaehler
      if counter /= 0 then
        counter := counter - 1;
      else
        counter := gr;
        for i in 0 to totalStackNumber-1 loop
          remain(i) := params(i)(parameterBreite - 1 downto 3);
          if params(i)(2 downto 0) = ``001`` then
            klasse(i) := ``110``;
          else
            klasse(i) := params(i)(2 downto 0);
          end if;
          if klasse(i) = ``000`` then
            remain(i) := granularity;
          end if;
        end loop;
      end if;
 
       -Latenzen von Decode?
      if Invalid = '0' and latency /= ``00`` then
        latenzen(lastScheduled) := latency;
      end if;     
 
       - Prioritaeten fuer Sortierung vorbereiten
      for i in 0 to totalStackNumber-1 loop
        
         - Issue Threashold! (>=3)
        if unsigned(fi(i)) < 3 then
          full := '0';
        else
          full := '1';
        end if;
        
         - Das erste bit der Klasse sagt, ob mehr als der Anteil erlaubt ist.
         - also nicht bei exakt, max, short
        if klasse(i)(2) = '1'  and unsigned(remain(i)) = 0 then
          darf := '0';
        else
          darf := '1';
        end if;
 
         - 1 bit geht|3 bit Klasse|n bit Resttakte
        priorities(i)(parameterBreite-4 downto 0) := remain(i);
        priorities(i)(parameterBreite-1 downto parameterBreite-3) := klasse(i);
        priorities(i)(parameterBreite) :=  (not (latenzen(i)(0) or latenzen(i)(1))
                                            and hwActive(i) and swActive(i)
                                            and not lockNeeded(i)
                                            and (full or opsExecution(i))
                                            and darf);
                     
      end loop;   - i
 
        
       - den groessten suchen
      for i in 0 to totalStackNumber-1 loop
        m(i):= i;
      end loop;
 
       - Der Vergleicherbaum.
      for j in 0 to ld_totalStackNumber-1 loop
        for i in 0 to (totalStackNumber/2**(j+1))-1 loop
          if priorities(m((2*i+1)*2**j))>priorities(m((2*i)*2**j)) then
            m((2*i)*2**j):=m((2*i+1)*2**j);
          end if;
        end loop;
      end loop;
 
      k:=m(0);
       - den groessten oder invalid weitergeben
      if priorities(k)(parameterBreite) = '1' then
        IdThreadTag   <= conv_std_logic_vector(k,ld_totalStackNumber);
        IdInvalid     <= '0';
        Invalid       := '0';
        lastScheduled := k;
        remain(k)     := unsigned(remain(k)) - 1;
      else
        IdInvalid     <= '1';
        Invalid       := '1';
      end if;
      
       - Latenzen werden dem Thread angerechnet
      for i in 0 to totalStackNumber-1 loop
        if unsigned(latenzen(i)) /= 0  and unsigned(remain(i)) /= 0 then
          remain(i) := unsigned(remain(i)) - 1;
        end if;
      end loop;   - i
      
       - Wechsle die Klasse von min,remain>0 (gleich ex) zu min,remain<0
      for i in 0 to totalStackNumber-1 loop
        if unsigned(remain(i)) = 0 and klasse(i) = ``110`` and params(i)(2 downto 0)= ``001`` then
          klasse(i) := ``001``;
          remain(i) := granularity;
        end if;
      end loop;   - i
      
       - Latenzen runterzaehlen
      for i in 0 to totalStackNumber-1 loop
        if unsigned(latenzen(i)) /= 0 then
          latenzen(i) := unsigned(latenzen(i)) - 1;
        end if;
      end loop;   - i
 
    end if;
  end process p;
 
end GP_Scheduler;
 
 ------------------------------------
 ------------------------------------
 
architecture EDF_Scheduler of PriorityManager is
 
   - Typdeklarationen
  subtype param_int   is std_logic_vector(parameterBreite-1 downto 0);
  subtype prio_int    is std_logic_vector(parameterBreite downto 0);
  subtype fi_int      is std_logic_vector(3 downto 0);
  subtype latenz_int  is std_logic_vector(1 downto 0);
  type param_int_arr  is array(0 to totalStackNumber-1) of param_int;
  type prio_int_arr   is array(0 to totalStackNumber-1) of prio_int;
  type fi_int_arr     is array(0 to totalStackNumber-1) of fi_int;
  type latenz_int_arr is array(0 to totalStackNumber-1) of latenz_int;
  type m_arr          is array(0 to totalStackNumber-1) of integer range 0 to totalStackNumber-1;
   - Interne Signale
  signal param         : param_int_arr;         
  signal fi            : fi_int_arr;
  
 
begin   - EDF_Scheduler
  
  g: for i in 0 to totalStackNumber-1 generate
    param(i) <= parameter((parameterBreite*(i+1))-1 downto parameterBreite*i);
    fi(i) <= fill((4*(i+1))-1 downto 4*i); 
  end generate g;
 
  
   - purpose: Berechnet den naechsten auszufuehrenden Thread
   - Der ausfuehrbare Thread mit den fruehesten Deadline kommt dran
   - type   : sequential
   - inputs : clk, reset, see entity
   - outputs: IdThreadTag, IdInvalid
  p: process (clk, reset)
 
    variable params     : param_int_arr;            - Temporaere variablen
    variable priorities : prio_int_arr;
    variable k          : integer range 0 to totalStackNumber-1;
    variable full       : std_logic;
    variable latenzen   : latenz_int_arr;
    variable m          : m_arr;
     - ab hier koennen es auch Signale sein
    variable lastScheduled : integer range 0 to totalStackNumber-1;
    variable Invalid       : std_logic;
 
  begin   - process p
        
    if reset = '1' then                  - asynchronous reset (active high)
 
      lastScheduled := 0;
      k             := 0;
      IdInvalid     <= '0';
      Invalid       := '0';
      
      for i in 0 to ld_totalStackNumber-1 loop
        IdThreadTag(i) <= '0';
      end loop;
      
      for i in 0 to totalStackNumber-1 loop
        latenzen(i) := conv_std_logic_vector(0,2);
        for j in 0 to parameterBreite-1 loop
          params(i)(j) := '0';
        end loop;
      end loop;
 
    elsif clk'event and clk = '1' then   - rising clock edge
 
       - Wenn ein Signal ankommt, wird die Deadline uebernommen.
       - Mit jedem Takt wird sie runtergezaehlt, so dass der
       - Thread mit der naechsten Deadline die kleinste Zahl
       - in parameters hat.
      for i in 0 to totalStackNumber-1 loop
        if signalArrived(i) = '1' then
          params(i) := param(i);
        else
          if unsigned(params(i)) /= 0 then
            params(i) := unsigned(params(i)) - 1;
          end if;
        end if;
      end loop;   - i
 
       - Latenz von der decode Stufe gemeldet
      if Invalid = '0' and latency /= ``00`` then
        latenzen(lastScheduled) := latency;
      end if;     
 
       - Prioritaeten fuer Sortierung vorbereiten
      for i in 0 to totalStackNumber-1 loop
        
         - Issue Threshold (>=3)
        if unsigned(fi(i)) < 3 then
          full := '0';
        else
          full := '1';
        end if;
              
        priorities(i)(parameterBreite-1 downto 0) := params(i);
        priorities(i)(parameterBreite) := not (not (latenzen(i)(0) or latenzen(i)(1))
                                               and hwActive(i) and swActive(i)
                                               and not lockNeeded(i)
                                               and (full or opsExecution(i)));
      end loop;   - i
        
       - Den niedrigsten! suchen. Hier negative Logik
      for i in 0 to totalStackNumber-1 loop
        m(i):= i;
      end loop;
 
       - Der Vergleicherbaum.
      for j in 0 to ld_totalStackNumber-1 loop
        for i in 0 to (totalStackNumber/2**(j+1))-1 loop
          if priorities(m((2*i+1)*2**j))<priorities(m((2*i)*2**j)) then
            m((2*i)*2**j):=m((2*i+1)*2**j);
          end if;
        end loop;
      end loop;
 
      k:=m(0);
 
       - Niedrigsten oder invalid weitergeben zu decode
      if priorities(k)(parameterBreite) = '0' then
        IdThreadTag   <= conv_std_logic_vector(k,ld_totalStackNumber);
        IdInvalid     <= '0';
        Invalid       := '0';
        lastScheduled := k;
      else
        IdInvalid     <= '1';
        Invalid       := '1';
      end if;
      
       - Alle Threads haben eine Latenz abgesessen
      for i in 0 to totalStackNumber-1 loop
        if unsigned(latenzen(i)) /= 0 then
          latenzen(i) := unsigned(latenzen(i)) - 1;
        end if;
      end loop;   - i
 
    end if;
  end process p;
 
end EDF_Scheduler;
 
 ---------------------------------
 ---------------------------------
 
 - Dies wird einfach ignoriert, er nimmt die letzte architecture
configuration PriorityConfig of PriorityManager is
  for EDF_Scheduler
  end for;
end PriorityConfig;
 

next up previous contents
Next: Fetch-Einheit Up: VHDL-Quellen Previous: VHDL-Quellen   Inhalt
Alexander Schulz
2000-06-18