// ************************************************************************** //
//                                                                            //
//    eses                   eses                                             //
//   eses                     eses                                            //
//  eses    eseses  esesese    eses   Embedded Systems Group                  //
//  ese    ese  ese ese         ese                                           //
//  ese    eseseses eseseses    ese   Department of Computer Science          //
//  eses   eses          ese   eses                                           //
//   eses   eseses  eseseses  eses    University of Kaiserslautern            //
//    eses                   eses                                             //
//                                                                            //
// ************************************************************************** //
// This module implements a Switch node that depending on the boolean input   //
// stream sel, forwards the values read from input x to one of the outputs y1 //
// or y0.                                                                     //
// ************************************************************************** //


macro val(x) = x.0;
macro clk(x) = x.1;

module Switch(event (bool * bool) sel,event (int * bool) x,y0,y1) {
    loop {
        // await trigger event: not that clk(x) without clk(sel) is useless, 
        // since one cannot decide about the further behavior
        if(clk(sel) or clk(y0) or clk(y1)) {
            // ensure clock consistency
            if(clk(sel)) {
                clk(x)  = true;
                clk(y0) = !val(sel);
                clk(y1) =  val(sel);
            }
            if(clk(y0)) {
                clk(sel) = true;
                val(sel) = false;
                clk(x)   = true;
                clk(y1)  = false;
            }
            if(clk(y1)) {
                clk(sel) = true;
                val(sel) = true;
                clk(x)   = true;
                clk(y0)  = false;
            }
            // produce output values
            if(val(sel))
                val(y1) = val(x);
            else
                val(y0) = val(x);
        }
        // negative clock information
        if(!clk(x) | !clk(sel) | !clk(y1) & !clk(y0)) {
            // ensure clock consistency
            clk(sel) = false;
            clk(x)   = false;
            clk(y1)  = false;
            clk(y0)  = false;
       }
        pause;
    }
}