recalculate the timing initial values so that the default settings work for imageon/zc702

// Copyright (c) 2013 Nokia, Inc.
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Vector::*;
import Clocks::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;
import Arith::*;

`ifdef ZC706
typedef 24 HdmiBits;
`else
typedef 16 HdmiBits;
`endif

interface HDMI#(type pixelType);
    method Bit#(1) hdmi_vsync;
    method Bit#(1) hdmi_hsync;
    method Bit#(1) hdmi_de;
    method pixelType hdmi_data;
    interface Clock hdmi_clock_if;
    interface Reset deleteme_unused_reset;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setDePixel(Bit#(12) porch, Bit#(12) width, Bit#(12) visible, Bit#(12) last, Bit#(12) mid);
    method Action setDeLine(Bit#(11) porch, Bit#(11) width, Bit#(11) visible, Bit#(11) last, Bit#(11) mid);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v, Bit#(32) vs);
endinterface

interface HdmiGenerator#(type pixelType);
    interface HdmiInternalRequest control;
    interface Get#(VideoData#(pixelType)) rgb888;
    interface Put#(Bit#(32)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
   SyncPulseIfc startDMA, HdmiInternalIndication indication)(HdmiGenerator#(Rgb888));
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) dePixelEnd <- mkSyncReg(1920 + 192 + 44 + 44-1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelWidth <- mkSyncReg(44 + 44 - 1 + 44, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelPorch <- mkSyncReg(44 + 44 - 1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelVisible <- mkSyncReg(44 + 44 - 1 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineEnd <- mkSyncReg(1080 + 45-1, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineWidth <- mkSyncReg(3 + 5, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLinePorch <- mkSyncReg(3, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineVisible <- mkSyncReg(3 + 41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc sendVsyncIndication <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);

    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Reg#(Bit#(1)) patternIndex0 <- mkReg(0);
    Reg#(Bit#(1)) patternIndex1 <- mkReg(0);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bool) dataEnable <- mkReg(False);
    Reg#(Bool) lineVisible <- mkReg(False);
    Reg#(Bit#(1)) vsync <- mkReg(0);
    Reg#(Bit#(1)) hsync <- mkReg(0);
    Reg#(Bit#(32)) vsyncCounter <- mkReg(0);

    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    Reg#(Bit#(32)) underflowCount <- mkReg(0);
    Reg#(Bit#(32)) underflowCountAxi <- mkSyncReg(0, defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(32)) counter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsed <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsedVsync <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    SyncBitIfc#(Bit#(32)) vsyncCounters <- mkSyncBits(0, defaultClock, defaultReset, axi_clock, axi_reset);

    rule vsyncaxi;
       vsyncCounters.send(vsyncCounter);
    endrule

    rule axicyclecount;
       counter <= counter + 1;
    endrule

    rule vsyncReceived if (sendVsyncIndication.pulse());
       elapsed <= counter;
       elapsedVsync <= vsyncCounters.read();
       indication.vsync(extend(elapsed - counter), vsyncCounter - vsyncCounter);
       //waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (pixelCount == dePixelEnd) begin
           pixelCount <= 0;
           dataEnable <= False;
           patternIndex0 <= 0;
           if (lineCount == deLineEnd) begin
               lineCount <= 0;
               patternIndex1 <= 0;
               lineVisible <= False;
               testPatternEnabled <= shadowTestPatternEnabled;
               if (waitingForVsync)
	          sendVsyncIndication.send();
           end
           else begin
               if (lineCount == deLineVisible)
                   lineVisible <= True;
               lineCount <= lineCount+1;
               if (lineCount >= lineMidpoint)
                   patternIndex1 <= 1;
           end
        end
        else begin
           if (lineCount == deLinePorch) begin
              vsync <= 1;
              if (pixelCount == 0 && testPatternEnabled == 0) begin
                  vsyncCounter <= vsyncCounter+1;
                  startDMA.send();
              end
           end
           else if (lineCount == deLineWidth)
              vsync <= 0;
           if (pixelCount == dePixelPorch)
              hsync <= 1;
           else if (pixelCount == dePixelWidth)
              hsync <= 0;
           if (pixelCount == dePixelVisible)
               dataEnable <= lineVisible;
           pixelCount <= pixelCount + 1;
           if (pixelCount == pixelMidpoint)
               patternIndex0 <= 1;
        end
    endrule

    rule output_data_rule if (!dataEnable);
        rgb888StageReg <= VideoData {de: 0, pixel: unpack(0), vsync: vsync, hsync: hsync };
    endrule

    rule testpattern_rule if (testPatternEnabled != 0 && dataEnable);
        rgb888StageReg <= VideoData {de: 1, vsync: 0, hsync: 0, pixel: unpack(patternRegs[{patternIndex1, patternIndex0}])};
    endrule

    interface Put request;
        method Action put(Bit#(32) v) if (testPatternEnabled == 0 && dataEnable);
           rgb888StageReg <= VideoData {de: 1, vsync: 0, hsync: 0, pixel: unpack(v[23:0])};
        endmethod
    endinterface: request

    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setDePixel(Bit#(12) porch, Bit#(12) width, Bit#(12) visible, Bit#(12) last, Bit#(12) mid);
            dePixelWidth <= width;
            dePixelPorch <= porch;
            dePixelVisible <= visible;
            dePixelEnd <= last;
            pixelMidpoint <= mid;
        endmethod
        method Action setDeLine(Bit#(11) porch, Bit#(11) width, Bit#(11) visible, Bit#(11) last, Bit#(11) mid);
            deLineWidth <= width;
            deLinePorch <= porch;
            deLineVisible <= visible;
            deLineEnd <= last;
            lineMidpoint <= mid;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
   interface Get rgb888;
      method ActionValue#(VideoData#(Rgb888)) get();
	 return rgb888StageReg;
      endmethod
   endinterface
endmodule

module mkHDMI#(Get#(VideoData#(pixelType)) videoInput)(HDMI#(Bit#(pixelsz)))
   provisos (Bits#(VideoData#(pixelType), a__), Bits#(pixelType,pixelsz));
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Wire#(VideoData#(pixelType)) video <- mkDWire(unpack(0));
   rule getvideo;
      let v <- videoInput.get();
      video <= v;
   endrule

   method Bit#(1) hdmi_vsync;
      return video.vsync;
   endmethod
   method Bit#(1) hdmi_hsync;
      return video.hsync;
   endmethod
   method Bit#(1) hdmi_de;
      return video.de;
   endmethod
   method Bit#(pixelsz) hdmi_data;
      return pack(video.pixel);
   endmethod
   interface hdmi_clock_if = defaultClock;
   interface deleteme_unused_reset = defaultReset;
endmodule

interface Rgb888ToYyuv;
   interface Put#(VideoData#(Rgb888)) rgb888;
   interface Get#(VideoData#(Yyuv)) yyuv;
endinterface

(* synthesize *)
module mkRgb888ToYyuv(Rgb888ToYyuv);
    Reg#(VideoData#(Rgb888))                        stage0Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444Intermediates))           stage1Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Vector#(2,Vector#(3,Bit#(16))))) stage2Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444))                        stage3Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yyuv))                          stage4Reg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    rule stage1_rule;
        let previous = stage0Reg;
        let pixel = previous.pixel;
        stage1Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule stage2_rule;
        let previous = stage1Reg;
       Vector#(4, Vector#(3, Bit#(16))) vprev = previous.pixel;
       Vector#(2, Vector#(3, Bit#(16))) vnext;
       vnext[0] = vadd(vprev[0], vprev[1]);
       vnext[1] = vadd(vprev[2], vprev[3]);

       stage2Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	    pixel: (previous.de != 0) ? vnext : unpack(0)
        };
    endrule

   rule stage3_rule;
      let previous = stage2Reg;
       Vector#(2, Vector#(3, Bit#(16))) vprev = previous.pixel;
      Yuv444 pixel = yuv444FromVector(vrshift(vadd(vprev[0], vprev[1]), 8));

      stage3Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	 pixel: (previous.de != 0) ? pixel : unpack(0) };
   endrule

    rule stage4_rule;
        let previous = stage3Reg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Yyuv data = Yyuv { uv: evenOddPixelReg ? previous.pixel.u : previous.pixel.v,
                           yy: previous.pixel.y };
        stage4Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: data
        };
    endrule

   interface Put rgb888;
      method Action put(VideoData#(Rgb888) v);
	 stage0Reg <= v;
      endmethod
   endinterface
   interface Get yyuv;
      method ActionValue#(VideoData#(Yyuv)) get();
	 return stage4Reg;
      endmethod
   endinterface
endmodule

// Copyright (c) 2013 Nokia, Inc.
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Vector::*;
import Clocks::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import SyncBits::*;
import YUV::*;
import Arith::*;

`ifdef ZC706
typedef 24 HdmiBits;
`else
typedef 16 HdmiBits;
`endif

interface HDMI#(type pixelType);
    method Bit#(1) hdmi_vsync;
    method Bit#(1) hdmi_hsync;
    method Bit#(1) hdmi_de;
    method pixelType hdmi_data;
    interface Clock hdmi_clock_if;
    interface Reset deleteme_unused_reset;
endinterface

interface HdmiInternalRequest;
    method Action setTestPattern(Bit#(1) v);
    method Action setPatternColor(Bit#(32) v);
    method Action setDePixel(Bit#(12) porch, Bit#(12) width, Bit#(12) visible, Bit#(12) last, Bit#(12) mid);
    method Action setDeLine(Bit#(11) porch, Bit#(11) width, Bit#(11) visible, Bit#(11) last, Bit#(11) mid);
    method Action waitForVsync(Bit#(32) unused);
endinterface
interface HdmiInternalIndication;
    method Action vsync(Bit#(64) v, Bit#(32) vs);
endinterface

interface HdmiGenerator#(type pixelType);
    interface HdmiInternalRequest control;
    interface Get#(VideoData#(pixelType)) rgb888;
    interface Put#(Bit#(32)) request;
endinterface

module mkHdmiGenerator#(Clock axi_clock, Reset axi_reset,
   SyncPulseIfc startDMA, HdmiInternalIndication indication)(HdmiGenerator#(Rgb888));
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    // 1920 * 1080
    Reg#(Bit#(12)) dePixelEnd <- mkSyncReg(0, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelWidth <- mkSyncReg(3, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelPorch <- mkSyncReg(192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) dePixelVisible <- mkSyncReg(1920 + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(12)) pixelMidpoint <- mkSyncReg((1920/2) + 192, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineEnd <- mkSyncReg(0, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineWidth <- mkSyncReg(3, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLinePorch <- mkSyncReg(41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) deLineVisible <- mkSyncReg(1080+41, axi_clock, axi_reset, defaultClock);
    Reg#(Bit#(11)) lineMidpoint <- mkSyncReg((1080/2) + 41, axi_clock, axi_reset, defaultClock);
    Vector#(4, Reg#(Bit#(24))) patternRegs <- replicateM(mkSyncReg(24'h00FFFFFF, axi_clock, axi_reset, defaultClock));
    Reg#(Bit#(1)) shadowTestPatternEnabled <- mkSyncReg(1, axi_clock, axi_reset, defaultClock);
    Reg#(Bool) waitingForVsync <- mkSyncReg(False, axi_clock, axi_reset, defaultClock);
    SyncPulseIfc sendVsyncIndication <- mkSyncHandshake(defaultClock, defaultReset, axi_clock);

    Reg#(Bit#(11)) lineCount <- mkReg(0);
    Reg#(Bit#(12)) pixelCount <- mkReg(0);
    Reg#(Bit#(1)) patternIndex0 <- mkReg(0);
    Reg#(Bit#(1)) patternIndex1 <- mkReg(0);
    Reg#(Bit#(1)) testPatternEnabled <- mkReg(1);
    Reg#(Bool) dataEnable <- mkReg(False);
    Reg#(Bool) lineVisible <- mkReg(False);
    Reg#(Bit#(1)) vsync <- mkReg(0);
    Reg#(Bit#(1)) hsync <- mkReg(0);

    Reg#(VideoData#(Rgb888)) rgb888StageReg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    Reg#(Bit#(32)) underflowCount <- mkReg(0);
    Reg#(Bit#(32)) underflowCountAxi <- mkSyncReg(0, defaultClock, defaultReset, axi_clock);
    Reg#(Bit#(32)) counter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) vsyncCounter <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsed <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);
    Reg#(Bit#(32)) elapsedVsync <- mkReg(0, clocked_by axi_clock, reset_by axi_reset);

    rule axicyclecount;
       counter <= counter + 1;
    endrule

    rule vsyncCount if (startDMA.pulse());
       vsyncCounter <= vsyncCounter+1;
    endrule
    rule vsyncReceived if (sendVsyncIndication.pulse());
       elapsed <= counter;
       elapsedVsync <= vsyncCounter;
       indication.vsync(extend(elapsed - counter), vsyncCounter - vsyncCounter);
       //waitingForVsync <= False;
    endrule

    rule init_pattern;
        patternRegs[1] <= 24'h00FF0000; // blue
        patternRegs[2] <= 24'h0000FF00; // green
        patternRegs[3] <= 24'h000000FF; // red
        //patternRegs[1] <= 32'h80ff80ff; // yuv422 white
        //patternRegs[2] <= 32'h2c961596; // yuv422 green
        //patternRegs[3] <= 32'hff1d6b1d; // yuv422 red
    endrule

    rule inc_counters;
        if (pixelCount == dePixelEnd) begin
           pixelCount <= 0;
           dataEnable <= False;
           patternIndex0 <= 0;
           if (lineCount == deLineEnd) begin
               lineCount <= 0;
               patternIndex1 <= 0;
               lineVisible <= False;
               testPatternEnabled <= shadowTestPatternEnabled;
               if (waitingForVsync)
	          sendVsyncIndication.send();
           end
           else begin
               if (lineCount == deLineVisible)
                   lineVisible <= True;
               lineCount <= lineCount+1;
               if (lineCount >= lineMidpoint)
                   patternIndex1 <= 1;
           end
        end
        else begin
           if (lineCount == deLinePorch) begin
              vsync <= 1;
              if (pixelCount == 0 && testPatternEnabled == 0)
                  startDMA.send();
           end
           else if (lineCount == deLineWidth)
              vsync <= 0;
           if (pixelCount == dePixelPorch)
              hsync <= 1;
           else if (pixelCount == dePixelWidth)
              hsync <= 0;
           if (pixelCount == dePixelVisible)
               dataEnable <= lineVisible;
           pixelCount <= pixelCount + 1;
           if (pixelCount == pixelMidpoint)
               patternIndex0 <= 1;
        end
    endrule

    rule output_data_rule if (!dataEnable);
        rgb888StageReg <= VideoData {de: 0, pixel: unpack(0), vsync: vsync, hsync: hsync };
    endrule

    rule testpattern_rule if (testPatternEnabled != 0 && dataEnable);
        rgb888StageReg <= VideoData {de: 1, vsync: 0, hsync: 0, pixel: unpack(patternRegs[{patternIndex1, patternIndex0}])};
    endrule

    interface Put request;
        method Action put(Bit#(32) v) if (testPatternEnabled == 0 && dataEnable);
           rgb888StageReg <= VideoData {de: 1, vsync: 0, hsync: 0, pixel: unpack(v[23:0])};
        endmethod
    endinterface: request

    interface HdmiInternalRequest control;
        method Action setPatternColor(Bit#(32) v);
            patternRegs[0] <= v[23:0];
        endmethod
        method Action setTestPattern(Bit#(1) v);
            shadowTestPatternEnabled <= v;
        endmethod
        method Action setDePixel(Bit#(12) porch, Bit#(12) width, Bit#(12) visible, Bit#(12) last, Bit#(12) mid);
            dePixelWidth <= width;
            dePixelPorch <= porch;
            dePixelVisible <= visible;
            dePixelEnd <= last;
            pixelMidpoint <= mid;
        endmethod
        method Action setDeLine(Bit#(11) porch, Bit#(11) width, Bit#(11) visible, Bit#(11) last, Bit#(11) mid);
            deLineWidth <= width;
            deLinePorch <= porch;
            deLineVisible <= visible;
            deLineEnd <= last;
            lineMidpoint <= mid;
        endmethod
        method Action waitForVsync(Bit#(32) unused);
            waitingForVsync <= True;
        endmethod
    endinterface
   interface Get rgb888;
      method ActionValue#(VideoData#(Rgb888)) get();
	 return rgb888StageReg;
      endmethod
   endinterface
endmodule

module mkHDMI#(Get#(VideoData#(pixelType)) videoInput)(HDMI#(Bit#(pixelsz)))
   provisos (Bits#(VideoData#(pixelType), a__), Bits#(pixelType,pixelsz));
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();
   Wire#(VideoData#(pixelType)) video <- mkDWire(unpack(0));
   rule getvideo;
      let v <- videoInput.get();
      video <= v;
   endrule

   method Bit#(1) hdmi_vsync;
      return video.vsync;
   endmethod
   method Bit#(1) hdmi_hsync;
      return video.hsync;
   endmethod
   method Bit#(1) hdmi_de;
      return video.de;
   endmethod
   method Bit#(pixelsz) hdmi_data;
      return pack(video.pixel);
   endmethod
   interface hdmi_clock_if = defaultClock;
   interface deleteme_unused_reset = defaultReset;
endmodule

interface Rgb888ToYyuv;
   interface Put#(VideoData#(Rgb888)) rgb888;
   interface Get#(VideoData#(Yyuv)) yyuv;
endinterface

(* synthesize *)
module mkRgb888ToYyuv(Rgb888ToYyuv);
    Reg#(VideoData#(Rgb888))                        stage0Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444Intermediates))           stage1Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Vector#(2,Vector#(3,Bit#(16))))) stage2Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yuv444))                        stage3Reg <- mkReg(unpack(0));
    Reg#(VideoData#(Yyuv))                          stage4Reg <- mkReg(unpack(0));
    Reg#(Bool) evenOddPixelReg <- mkReg(False);

    rule stage1_rule;
        let previous = stage0Reg;
        let pixel = previous.pixel;
        stage1Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: (previous.de != 0) ? rgbToYuvIntermediates(pixel) : unpack(0)
        };
    endrule

    rule stage2_rule;
        let previous = stage1Reg;
       Vector#(4, Vector#(3, Bit#(16))) vprev = previous.pixel;
       Vector#(2, Vector#(3, Bit#(16))) vnext;
       vnext[0] = vadd(vprev[0], vprev[1]);
       vnext[1] = vadd(vprev[2], vprev[3]);

       stage2Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	    pixel: (previous.de != 0) ? vnext : unpack(0)
        };
    endrule

   rule stage3_rule;
      let previous = stage2Reg;
       Vector#(2, Vector#(3, Bit#(16))) vprev = previous.pixel;
      Yuv444 pixel = yuv444FromVector(vrshift(vadd(vprev[0], vprev[1]), 8));

      stage3Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
	 pixel: (previous.de != 0) ? pixel : unpack(0) };
   endrule

    rule stage4_rule;
        let previous = stage3Reg;
        if (previous.de != 0)
            evenOddPixelReg <= !evenOddPixelReg;
        Yyuv data = Yyuv { uv: evenOddPixelReg ? previous.pixel.u : previous.pixel.v,
                           yy: previous.pixel.y };
        stage4Reg <= VideoData {
            vsync: previous.vsync, hsync: previous.hsync, de: previous.de,
            pixel: data
        };
    endrule

   interface Put rgb888;
      method Action put(VideoData#(Rgb888) v);
	 stage0Reg <= v;
      endmethod
   endinterface
   interface Get yyuv;
      method ActionValue#(VideoData#(Yyuv)) get();
	 return stage4Reg;
      endmethod
   endinterface
endmodule


added mkGatedBramServerMux

added mkGatedBramServerMux

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import ClientServer ::*;
import BRAM         ::*;
import Vector       ::*;
import FIFO         ::*;
import SpecialFIFOs :: *;

interface BramServerMux#(numeric type aszn, type dtype);
   interface BRAMServer#(Bit#(aszn), dtype) bramServer;
endinterface

module mkBramServerMux#(Vector#(numServers, BRAMServer#(Bit#(asz),dtype)) bramServers)(BramServerMux#(aszn,dtype))
   provisos (Add#(1,a__,numServers),
	     Log#(numServers,csz),
	     Add#(asz,csz,aszn),
	     Bits#(dtype,dsz),
	     Bits#(Tuple2#(Bit#(csz), BRAM::BRAMRequest#(Bit#(asz), dtype)), c__)
	     );
   let numServers = valueOf(numServers);
   FIFO#(dtype) responseFifo <- mkPipelineFIFO();
   for (Integer i = 0; i < numServers; i = i + 1) begin
      (* descending_urgency = "respond" *)
      rule respond;
         let response <- bramServers[i].response.get();
         responseFifo.enq(response);
      endrule
   end
   interface BRAMServer bramServer;
      interface Put request;
	 method Action put(BRAMRequest#(Bit#(aszn), dtype) request);
	    Bit#(csz) clientNumber = request.address[valueOf(aszn)-1:valueOf(asz)];
            bramServers[clientNumber].request.put( BRAMRequest {
					    write: request.write,
					    responseOnWrite: request.responseOnWrite,
					    address: truncate(request.address),
					    datain: request.datain });
	 endmethod
      endinterface
      interface Get response;
	 method ActionValue#(dtype) get();
	    responseFifo.deq();
	    return responseFifo.first();
	 endmethod
      endinterface
   endinterface
endmodule

module mkGatedBramServerMux#(Reg#(Bool) gate, Vector#(numServers, BRAMServer#(Bit#(asz),dtype)) bramServers)(BramServerMux#(aszn,dtype))
   provisos (Add#(1,a__,numServers),
	     Log#(numServers,csz),
	     Add#(asz,csz,aszn),
	     Bits#(dtype,dsz),
	     Bits#(Tuple2#(Bit#(csz), BRAM::BRAMRequest#(Bit#(asz), dtype)), c__)
	     );
   let numServers = valueOf(numServers);
   FIFO#(dtype) responseFifo <- mkPipelineFIFO();
   for (Integer i = 0; i < numServers; i = i + 1) begin
      (* descending_urgency = "respond" *)
      rule respond if (gate);
         let response <- bramServers[i].response.get();
         responseFifo.enq(response);
      endrule
   end
   interface BRAMServer bramServer;
      interface Put request;
	 method Action put(BRAMRequest#(Bit#(aszn), dtype) request) if (gate);
	    Bit#(csz) clientNumber = request.address[valueOf(aszn)-1:valueOf(asz)];
            bramServers[clientNumber].request.put( BRAMRequest {
					    write: request.write,
					    responseOnWrite: request.responseOnWrite,
					    address: truncate(request.address),
					    datain: request.datain });
	 endmethod
      endinterface
      interface Get response;
	 method ActionValue#(dtype) get();
	    responseFifo.deq();
	    return responseFifo.first();
	 endmethod
      endinterface
   endinterface
endmodule

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import ClientServer ::*;
import BRAM         ::*;
import Vector       ::*;
import FIFO         ::*;
import SpecialFIFOs :: *;

interface BramServerMux#(numeric type aszn, type dtype);
   interface BRAMServer#(Bit#(aszn), dtype) bramServer;
endinterface

module mkBramServerMux#(Vector#(numServers, BRAMServer#(Bit#(asz),dtype)) bramServers)(BramServerMux#(aszn,dtype))
   provisos (Add#(1,a__,numServers),
	     Log#(numServers,csz),
	     Add#(asz,csz,aszn),
	     Bits#(dtype,dsz),
	     Bits#(Tuple2#(Bit#(csz), BRAM::BRAMRequest#(Bit#(asz), dtype)), c__)
	     );
   let numServers = valueOf(numServers);
   FIFO#(dtype) responseFifo <- mkPipelineFIFO();
   for (Integer i = 0; i < numServers; i = i + 1) begin
      rule respond;
         let response <- bramServers[i].response.get();
         responseFifo.enq(response);
      endrule
   end
   interface BRAMServer bramServer;
      interface Put request;
	 method Action put(BRAMRequest#(Bit#(aszn), dtype) request);
	    Bit#(csz) clientNumber = request.address[valueOf(aszn)-1:valueOf(asz)];
            bramServers[clientNumber].request.put( BRAMRequest {
					    write: request.write,
					    responseOnWrite: request.responseOnWrite,
					    address: truncate(request.address),
					    datain: request.datain });
	 endmethod
      endinterface
      interface Get response;
	 method ActionValue#(dtype) get();
	    responseFifo.deq();
	    return responseFifo.first();
	 endmethod
      endinterface
   endinterface
endmodule


fix commenting

fix commenting

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, int dir)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1j <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
   Reg#(Bit#(16)) k0j <- mkReg(0);
   Reg#(Bit#(16)) k0jm1 <- mkReg(0);
   BRAM1Port#(Bit#(lIndexWidth), Bit#(16)) k0  <- mkBRAM1Server(defaultValue);

/* The original algorithm B uses two vectors K0 and K1 to store two rows of the full L
 * matrix from algoritm A.  For any particular iteration, K[0][j-1] K[0][j]
 * and K[1][j-1] are used to compute K[1][j]
 *
 * Each cycle, K[1] is copied to K[0], and then a new K[1] is computed.  First, the
 * the previous K[0][j] is copied to K[0][j-1] and the previous K[1][j] is copied to
 * K[1][j-1].  Then a new K[1][j] is computed.
 *
 * In the revised version, a single vector is used, plus auxiliary registers.
 * First the old K[0][j] auxiliary is copied to K[0][j-1] and the K[1][j] auxiliary
 * is copied to K[1][j-1].  Then K[0][j] is read. Then K[1][j] is computed <and written> to
 * K[0][j].  When the row is finished, K[0] is effectively K[1]
 *
 */

  Stmt hirschB =
   seq
      jj <= 17;  // one cycle delay to permit the control registers to get set
      //$display("hirschB running %d %d %d %d dir %d",
	// aStartReg, aLenReg, bStartReg, bLenReg, dir);
      /* initialize K1 (stored in lMat) of temporary storage */
      for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj), datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    //$display("hirschB ii = %d", ii);
	    par
	       /* initialize pipelining */
	       jj <= 1;
	       k0j <= 0;
	       k1j <= 0;
	       action
		  let idx = ?;
		  if (dir == 1)
		     idx = aStartReg + ii - 1;  // 0 to aLen - 1
		  else
		     idx = aStartReg + aLenReg - ii;  // aLen-1 downto 0
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
	       endaction
	       /* Read b[j] */
	       action
		  let idx = ?;
		  if (dir == 1)
		     idx = bStartReg;
		  else
		     idx = bStartReg + bLenReg - 1;
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
	       endaction
	       /* start read of k0j */
	       matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: rStartReg + 1, datain: 0});
	    endpar
	    action
	       let ta <- strA.response.get(); /* read a[i] */
	       aData <= ta;
	    endaction

	    /* Loop through string B */
	    while (jj <= bLenReg)
	       seq
		  //$display("hirschB jj = %d", jj);
		  action
		     let tb <- strB.response.get();
		     let tk <- matL.response.get();
		     k0jm1 <= k0j;  /* pipeline from previous cycle */
		     k1jm1 <= k1j;
		     bData <= tb;   /* read b[j] from bram */
		     k0j <= tk;     /* read k[0][j] from bram */
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj-1), datain: k1j});
		  endaction
		  //$display("hirschB ii %d jj %d A %h B %h k1j", ii, jj, aData, bData, k1j);
		  action
		     let tmp = ?;
		     /* Read b[j] */
		     /* if backwards B[bStartReg + bLenReg - jj] */
		     action
			let idx = ?;
			if (dir == 1)
			   idx = bStartReg + jj;
			else
			   idx = bStartReg + bLenReg - jj - 1;
			strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
		     endaction
		     if (aData == bData)
			tmp = k0jm1 + 1;
		     else
		        tmp = max(k0j,k1jm1);
		     k1j <= tmp;
		     jj <= jj + 1;
		     /* start read of k0j */
		     matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: rStartReg + zeroExtend(jj+1), datain: 0});
		  endaction
		  //$display("     L[%d][%d] = %d ", ii, jj, k1j);
	       endseq
	    action
	       let tb <- strB.response.get();
	       let tk <- matL.response.get();
	       matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj-1), datain: k1j});
	    endaction
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) start, Bit#(7) length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(zeroExtend(bLenReg));
   endmethod

   interface FSM fsm = hB;

endmodule

// Copyright (c) 2014 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import StmtFSM::*;
import BRAM::*;
import MCSAlgorithm::*;

module mkHirschB#(BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strA, BRAMServer#(Bit#(strIndexWidth), Bit#(8)) strB, BRAMServer#(Bit#(lIndexWidth), Bit#(16)) matL, int dir)(MCSAlgorithm)
         provisos(Add#(0, 7, strIndexWidth),
	       Add#(0, 14, lIndexWidth));

   Reg#(Bit#(7)) aStartReg <- mkReg(0);
   Reg#(Bit#(7)) bStartReg <- mkReg(0);
   Reg#(Bit#(14)) rStartReg <- mkReg(0);
   Reg#(Bit#(7)) aLenReg <- mkReg(0);
   Reg#(Bit#(7)) bLenReg <- mkReg(0);
   Reg#(Bit#(7)) ii <- mkReg(0);
   Reg#(Bit#(7)) jj <- mkReg(0);
   Reg#(Bit#(8)) aData <- mkReg(0);
   Reg#(Bit#(8)) bData <- mkReg(0);
   Reg#(Bit#(16)) k1j <- mkReg(0);
   Reg#(Bit#(16)) k1jm1 <- mkReg(0);
   Reg#(Bit#(16)) k0j <- mkReg(0);
   Reg#(Bit#(16)) k0jm1 <- mkReg(0);
   BRAM1Port#(Bit#(lIndexWidth), Bit#(16)) k0  <- mkBRAM1Server(defaultValue);

/* The original algorithm B uses two vectors K0 and K1 to store two rows of the full L
 * matrix from algoritm A.  For any particular iteration, K[0][j-1] K[0][j]
 * and K[1][j-1] are used to compute K[1][j]
 *
 * Each cycle, K[1] is copied to K[0], and then a new K[1] is computed.  First, the
 * the previous K[0][j] is copied to K[0][j-1] and the previous K[1][j] is copied to
 * K[1][j-1].  Then a new K[1][j] is computed.
 *
 * In the revised version, a single vector is used, plus auxiliary registers.
 * First the old K[0][j] auxiliary is copied to K[0][j-1] and the K[1][j] auxiliary
 * is copied to K[1][j-1].  Then K[0][j] is read. Then K[1][j] is computed <and written> to
 * K[0][j].  When the row is finished, K[0] is effectively K[1]
 *
 */

  Stmt hirschB =
   seq
      jj <= 17;  // one cycle delay to permit the control registers to get set
      //$display("hirschB running %d %d %d %d dir %d",
	 aStartReg, aLenReg, bStartReg, bLenReg, dir);
      /* initialize K1 (stored in lMat) of temporary storage */
      for (jj <= 0; jj <= bLenReg; jj <= jj + 1)
	 seq
	    matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj), datain: 0});
	 endseq
      /* Loop through string a */
      for (ii <= 1; ii <= aLenReg; ii <= ii + 1)
	 seq
	    //$display("hirschB ii = %d", ii);
	    par
	       /* initialize pipelining */
	       jj <= 1;
	       k0j <= 0;
	       k1j <= 0;
	       action
		  let idx = ?;
		  if (dir == 1)
		     idx = aStartReg + ii - 1;  // 0 to aLen - 1
		  else
		     idx = aStartReg + aLenReg - ii;  // aLen-1 downto 0
		  strA.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
	       endaction
	       /* Read b[j] */
	       action
		  let idx = ?;
		  if (dir == 1)
		     idx = bStartReg;
		  else
		     idx = bStartReg + bLenReg - 1;
		  strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
	       endaction
	       /* start read of k0j */
	       matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: rStartReg + 1, datain: 0});
	    endpar
	    action
	       let ta <- strA.response.get(); /* read a[i] */
	       aData <= ta;
	    endaction

	    /* Loop through string B */
	    while (jj <= bLenReg)
	       seq
		  //$display("hirschB jj = %d", jj);
		  action
		     let tb <- strB.response.get();
		     let tk <- matL.response.get();
		     k0jm1 <= k0j;  /* pipeline from previous cycle */
		     k1jm1 <= k1j;
		     bData <= tb;   /* read b[j] from bram */
		     k0j <= tk;     /* read k[0][j] from bram */
		     matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj-1), datain: k1j});
		  endaction
		  //$display("hirschB ii %d jj %d A %h B %h k1j", ii, jj, aData, bData, k1j);
		  action
		     let tmp = ?;
		     /* Read b[j] */
		     /* if backwards B[bStartReg + bLenReg - jj] */
		     action
			let idx = ?;
			if (dir == 1)
			   idx = bStartReg + jj;
			else
			   idx = bStartReg + bLenReg - jj - 1;
			strB.request.put(BRAMRequest{write: False, responseOnWrite: False, address: idx, datain: 0});
		     endaction
		     if (aData == bData)
			tmp = k0jm1 + 1;
		     else
		        tmp = max(k0j,k1jm1);
		     k1j <= tmp;
		     jj <= jj + 1;
		     /* start read of k0j */
		     matL.request.put(BRAMRequest{write: False, responseOnWrite: False, address: rStartReg + zeroExtend(jj+1), datain: 0});
		  endaction
		  //$display("     L[%d][%d] = %d ", ii, jj, k1j);
	       endseq
	    action
	       let tb <- strB.response.get();
	       let tk <- matL.response.get();
	       matL.request.put(BRAMRequest{write: True, responseOnWrite: False, address: rStartReg + zeroExtend(jj-1), datain: k1j});
	    endaction
	 endseq
   endseq;

   FSM hB <- mkFSM(hirschB);

   method Action setupA(Bit#(7) start, Bit#(7) length);
      aStartReg <= start;
      aLenReg <= length;
   endmethod

   method Action setupB(Bit#(7) start, Bit#(7) length);
      bStartReg <= start;
      bLenReg <= length;
   endmethod

   method Action setupL(Bit#(14) start);
      rStartReg <= start;
   endmethod

   method Bit#(14) result();
      return(zeroExtend(bLenReg));
   endmethod

   interface FSM fsm = hB;

endmodule


try to fix translation cache

try to fix translation cache

import Vector::*;
import Assert::*;
import Ehr::*;
import Fifo::*;
import Types::*;
import ProcTypes::*;
import TlbTypes::*;

// vpn -> ppn of the page containing the intermediate page table
// entry at the lowest walk level

typedef struct {
    PageWalkLevel startLevel;
    Ppn ppn; // only valid when startLevel < maxPageWalkLevel
} TranslationCacheResp deriving(Bits, Eq, FShow);

interface TranslationCache;
    method Action req(Vpn vpn);
    method TranslationCacheResp resp;
    method Action deqResp;
    method Action addEntry(Vpn vpn, PageWalkLevel level, Ppn ppn);
    method Action flush;
    method Bool flush_done;
endinterface

// ordering:
// resp < {req, addEntry}
// req C addEntry
// flush C {req, addEntry} (flush is likely to have higher urgency)

// split translation cache

// translation cache for a specific level L. This stores the PTEs at level L.
interface SingleSplitTransCache;
    method ActionValue#(Maybe#(Ppn)) req(Vpn vpn);
    method Action addEntry(Vpn vpn, Ppn ppn);
    method Action flush;
endinterface

typedef 24 SplitTransCacheSize; // size from ISCA 2010 paper
typedef Bit#(TLog#(SplitTransCacheSize)) SplitTransCacheIdx;

module mkSingleSplitTransCache#(PageWalkLevel level)(SingleSplitTransCache);
    staticAssert(level > 0 && level <= maxPageWalkLevel, "illegal level");

    Vector#(SplitTransCacheSize, Reg#(Bool)) validVec <- replicateM(mkReg(False));
    Vector#(SplitTransCacheSize, Reg#(Vpn)) vpnVec <- replicateM(mkRegU);
    Vector#(SplitTransCacheSize, Reg#(Ppn)) ppnVec <- replicateM(mkRegU);

    // bit-LRU replacement. To reduce cycle time, we update LRU bits in the
    // next cycle after we touch an entry. However, when we have two
    // consecutive cycles inserting new entries, the latter insertion should
    // see the updates to LRU bits made by the former insertion; otherwise the
    // latter will insert to the same slot as the former one.
    Ehr#(2, Bit#(SplitTransCacheSize)) lruBit <- mkEhr(0);
    Reg#(Bit#(SplitTransCacheSize)) lruBit_upd = lruBit[0]; // write
    Reg#(Bit#(SplitTransCacheSize)) lruBit_add = lruBit[1]; // read
    // reg as 1 cycle delay for update LRU
    Ehr#(2, Maybe#(SplitTransCacheIdx)) updRepIdx <- mkEhr(Invalid);
    Reg#(Maybe#(SplitTransCacheIdx)) updRepIdx_deq = updRepIdx[0];
    Reg#(Maybe#(SplitTransCacheIdx)) updRepIdx_enq = updRepIdx[1];
    // randomly choose an LRU idx at replacement time
    Reg#(SplitTransCacheIdx) randIdx <- mkReg(0);

    // don't do anything at flush time
    PulseWire flushEn <- mkPulseWire;

    rule incRandIdx;
        randIdx <= randIdx + 1;
    endrule

    rule doUpdateRep(updRepIdx_deq matches tagged Valid .idx &&& !flushEn);
        updRepIdx_deq <= Invalid;
        // update LRU bits
        Bit#(SplitTransCacheSize) val = lruBit_upd;
        val[idx] = 1;
        if(val == maxBound) begin
            val = 0;
            val[idx] = 1;
        end
        lruBit_upd <= val;
    endrule

    method ActionValue#(Maybe#(Ppn)) req(Vpn vpn) if(updRepIdx_enq == Invalid && !flushEn);
        function Bool hit(SplitTransCacheIdx i);
            let vpn_match = getMaskedVpn(vpn, level) == getMaskedVpn(vpnVec[i], level);
            return validVec[i] && vpn_match;
        endfunction
        Vector#(SplitTransCacheSize, SplitTransCacheIdx) idxVec = genWith(fromInteger);
        if(find(hit, idxVec) matches tagged Valid .i) begin
            updRepIdx_enq <= Valid (i); // update LRU
            return Valid (ppnVec[i]);
        end
        else begin
            return Invalid;
        end
    endmethod

    method Action addEntry(Vpn vpn, Ppn ppn) if(updRepIdx_enq == Invalid && !flushEn);
        SplitTransCacheIdx addIdx;
        if(findIndex( \== (False) , readVReg(validVec) ) matches tagged Valid .idx) begin
            // get empty slot
            addIdx = pack(idx);
        end
        else begin
            // find LRU slot (lruBit[i] = 0 means i is LRU slot)
            Vector#(SplitTransCacheSize, Bool) isLRU = unpack(~lruBit_add);
            if(isLRU[randIdx]) begin
                addIdx = randIdx;
            end
            else if(findIndex(id, isLRU) matches tagged Valid .idx) begin
                addIdx = pack(idx);
            end
            else begin
                addIdx = 0; // this is actually impossible
                doAssert(False, "must have at least 1 LRU slot");
            end
        end
        // update slot
        validVec[addIdx] <= True;
        vpnVec[addIdx] <= getMaskedVpn(vpn, level);
        ppnVec[addIdx] <= ppn; // don't mask ppn, intermidate PTE point to a 4KB page
        // update LRU bits
        updRepIdx_enq <= Valid (addIdx);
    endmethod

    method Action flush;
        writeVReg(validVec, replicate(False));
        // also reset LRU bits
        lruBit_upd <= 0;
        updRepIdx_deq <= Invalid;
        // signal fire
        flushEn.send;
    endmethod
endmodule

(* synthesize *)
module mkSplitTransCache(TranslationCache);
    Vector#(TSub#(NumPageWalkLevels, 1), SingleSplitTransCache) caches;
    for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
        caches[i] <- mkSingleSplitTransCache(i + 1);
    end

    Fifo#(1, TranslationCacheResp) respQ <- mkPipelineFifo;

    method Action req(Vpn vpn);
        TranslationCacheResp resp;
        Vector#(TSub#(NumPageWalkLevels, 1), Maybe#(Ppn)) hits;
        for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
            hits[i] <- caches[i].req(vpn); // cached page walk level i+1
        end
        // XXX hit in lower level has priority
        if(findIndex(isValid, hits) matches tagged Valid .idx) begin
            resp = TranslationCacheResp {
                startLevel: zeroExtend(pack(idx)),
                ppn: validValue(hits[idx])
            };
        end
        else begin
            resp = TranslationCacheResp {
                startLevel: maxPageWalkLevel,
                ppn: ?
            };
        end
        respQ.enq(resp);
    endmethod

    method TranslationCacheResp resp = respQ.first;

    method Action deqResp;
        respQ.deq;
    endmethod

    // the guard makes resp < addEntry, so pending req is ordered before the
    // newly add entry (so in case of miss, the pending req could mark itself
    // waiting on the page walk that is just about to addEntry, and get the
    // bypass)
    method Action addEntry(Vpn vpn, PageWalkLevel level, Ppn ppn) if(respQ.notFull);
        doAssert(level > 0, "cannot be level 0");
        doAssert(level <= maxPageWalkLevel, "level too large");
        caches[level - 1].addEntry(vpn, ppn);
    endmethod

    method Action flush;
        for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
            caches[i].flush;
        end
    endmethod

    method Bool flush_done = True;
endmodule

import Vector::*;
import Assert::*;
import Ehr::*;
import Fifo::*;
import Types::*;
import ProcTypes::*;
import TlbTypes::*;

// vpn -> ppn of the page containing the intermediate page table
// entry at the lowest walk level

typedef struct {
    PageWalkLevel startLevel;
    Ppn ppn; // only valid when startLevel < maxPageWalkLevel
} TranslationCacheResp deriving(Bits, Eq, FShow);

interface TranslationCache;
    method Action req(Vpn vpn);
    method TranslationCacheResp resp;
    method Action deqResp;
    method Action addEntry(Vpn vpn, PageWalkLevel level, Ppn ppn);
    method Action flush;
    method Bool flush_done;
endinterface

// ordering:
// resp < {req, addEntry}
// req C addEntry
// flush C {req, addEntry} (flush is likely to have higher urgency)

// split translation cache

// translation cache for a specific level L. This stores the PTEs at level L.
interface SingleSplitTransCache;
    method ActionValue#(Maybe#(Ppn)) req(Vpn vpn);
    method Action addEntry(Vpn vpn, Ppn ppn);
    method Action flush;
endinterface

typedef 24 SplitTransCacheSize; // size from ISCA 2010 paper
typedef Bit#(TLog#(SplitTransCacheSize)) SplitTransCacheIdx;

module mkSingleSplitTransCache#(PageWalkLevel level)(SingleSplitTransCache);
    staticAssert(level > 0 && level <= maxPageWalkLevel, "illegal level");

    Vector#(SplitTransCacheSize, Reg#(Bool)) validVec <- replicateM(mkReg(False));
    Vector#(SplitTransCacheSize, Reg#(Vpn)) vpnVec <- replicateM(mkRegU);
    Vector#(SplitTransCacheSize, Reg#(Ppn)) ppnVec <- replicateM(mkRegU);

    // bit-LRU replacement. To reduce cycle time, we update LRU bits in the
    // next cycle after we touch an entry. However, when we have two
    // consecutive cycles inserting new entries, the latter insertion should
    // see the updates to LRU bits made by the former insertion; otherwise the
    // latter will insert to the same slot as the former one.
    Ehr#(2, Bit#(SplitTransCacheSize)) lruBit <- mkEhr(0);
    Reg#(Bit#(SplitTransCacheSize)) lruBit_upd = lruBit[0]; // write
    Reg#(Bit#(SplitTransCacheSize)) lruBit_add = lruBit[1]; // read
    // reg as 1 cycle delay for update LRU
    Ehr#(2, Maybe#(SplitTransCacheIdx)) updRepIdx <- mkEhr(Invalid);
    Reg#(Maybe#(SplitTransCacheIdx)) updRepIdx_deq = updRepIdx[0];
    Reg#(Maybe#(SplitTransCacheIdx)) updRepIdx_enq = updRepIdx[1];
    // randomly choose an LRU idx at replacement time
    Reg#(SplitTransCacheIdx) randIdx <- mkReg(0);

    // don't do anything at flush time
    PulseWire flushEn <- mkPulseWire;

    rule incRandIdx;
        randIdx <= randIdx + 1;
    endrule

    rule doUpdateRep(updRepIdx_deq matches tagged Valid .idx &&& !flushEn);
        updRepIdx_deq <= Invalid;
        // update LRU bits
        Bit#(SplitTransCacheSize) val = lruBit_upd;
        val[idx] = 1;
        if(val == maxBound) begin
            val = 0;
            val[idx] = 1;
        end
        lruBit_upd <= val;
    endrule

    method ActionValue#(Maybe#(Ppn)) req(Vpn vpn) if(updRepIdx_enq == Invalid && !flushEn);
        function Bool hit(SplitTransCacheIdx i);
            let vpn_match = getMaskedVpn(vpn, level) == getMaskedVpn(vpnVec[i], level);
            return validVec[i] && vpn_match;
        endfunction
        Vector#(SplitTransCacheSize, SplitTransCacheIdx) idxVec = genWith(fromInteger);
        if(find(hit, idxVec) matches tagged Valid .i) begin
            updRepIdx_enq <= Valid (i); // update LRU
            return Valid (ppnVec[i]);
        end
        else begin
            return Invalid;
        end
    endmethod

    method Action addEntry(Vpn vpn, Ppn ppn) if(updRepIdx_enq == Invalid && !flushEn);
        SplitTransCacheIdx addIdx;
        if(findIndex( \== (False) , readVReg(validVec) ) matches tagged Valid .idx) begin
            // get empty slot
            addIdx = pack(idx);
        end
        else begin
            // find LRU slot (lruBit[i] = 0 means i is LRU slot)
            Vector#(SplitTransCacheSize, Bool) isLRU = unpack(~lruBit_add);
            if(isLRU[randIdx]) begin
                addIdx = randIdx;
            end
            else if(findIndex(id, isLRU) matches tagged Valid .idx) begin
                addIdx = pack(idx);
            end
            else begin
                addIdx = 0; // this is actually impossible
                doAssert(False, "must have at least 1 LRU slot");
            end
        end
        // update slot
        validVec[addIdx] <= True;
        vpnVec[addIdx] <= getMaskedVpn(vpn, level);
        ppnVec[addIdx] <= getMaskedPpn(ppn, level);
        // update LRU bits
        updRepIdx_enq <= Valid (addIdx);
    endmethod

    method Action flush;
        writeVReg(validVec, replicate(False));
        // also reset LRU bits
        lruBit_upd <= 0;
        updRepIdx_deq <= Invalid;
        // signal fire
        flushEn.send;
    endmethod
endmodule

(* synthesize *)
module mkSplitTransCache(TranslationCache);
    Vector#(TSub#(NumPageWalkLevels, 1), SingleSplitTransCache) caches;
    for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
        caches[i] <- mkSingleSplitTransCache(i + 1);
    end

    Fifo#(1, TranslationCacheResp) respQ <- mkPipelineFifo;

    method Action req(Vpn vpn);
        TranslationCacheResp resp;
        Vector#(TSub#(NumPageWalkLevels, 1), Maybe#(Ppn)) hits;
        for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
            hits[i] <- caches[i].req(vpn); // cached page walk level i+1
        end
        // XXX hit in lower level has priority
        if(findIndex(isValid, hits) matches tagged Valid .idx) begin
            resp = TranslationCacheResp {
                startLevel: zeroExtend(pack(idx)),
                ppn: validValue(hits[idx])
            };
        end
        else begin
            resp = TranslationCacheResp {
                startLevel: maxPageWalkLevel,
                ppn: ?
            };
        end
        respQ.enq(resp);
    endmethod

    method TranslationCacheResp resp = respQ.first;

    method Action deqResp;
        respQ.deq;
    endmethod

    // the guard makes resp < addEntry, so pending req is ordered before the
    // newly add entry (so in case of miss, the pending req could mark itself
    // waiting on the page walk that is just about to addEntry, and get the
    // bypass)
    method Action addEntry(Vpn vpn, PageWalkLevel level, Ppn ppn) if(respQ.notFull);
        doAssert(level > 0, "cannot be level 0");
        doAssert(level <= maxPageWalkLevel, "level too large");
        caches[level - 1].addEntry(vpn, ppn);
    endmethod

    method Action flush;
        for(PageWalkLevel i = 0; i < maxPageWalkLevel; i = i+1) begin
            caches[i].flush;
        end
    endmethod

    method Bool flush_done = True;
endmodule


reindent LIFO

reindent LIFO

/*-
 * Copyright (c) 2015 Jonathan Woodrulf
 * All rights reserved.
 *
 * This software was developed by SRI International and the University of
 * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
 * ("CTSRD"), as part of the DARPA CRASH research programme.
 *
 * @BERI_LICENSE_topER_START@
 *
 * Licensed to BERI Open Systems C.I.C. (BERI) under one or more contributor
 * license agreements.  See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.  BERI licenses this
 * file to you under the BERI Hardware-Software License, Version 1.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *   http://www.beri-open-systems.org/legal/license-1-0.txt
 *
 * Unless required by applicable law or agreed to in writing, Work distributed
 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * @BERI_LICENSE_topER_END@
 *
 *****************************************************************************

 LF LIFO (Stack) library
 ===========

 This is a library of pure Bluespec LIFO components

 *****************************************************************************/

import ConfigReg::*;
import FIFO::*;
import FIFOF::*;
import RegFile::*;
import Vector::*;
import DReg    :: *;
import SpecialFIFOs :: *;

interface LF#(type data, numeric type depth);
   method Action push(data x);
   method ActionValue#(data) pop();
   method data peek();
   method Bool notFull();
   method Bool notEmpty();
   method Bit#(TLog#(depth)) remaining();
endinterface

// Equal to Bluespec equivelant
module mkUGLF(LF#(data, depth))
   provisos(Log#(depth,logDepth),Bits#(data, data_width));
   RegFile#(Bit#(logDepth),data)    rf <- mkRegFileWCF(minBound, maxBound); // BRAM
   Reg#(Bit#(logDepth))         top[2] <- mkCReg(2,0);

   Bit#(logDepth) thisTop = top[0];
   Bit#(logDepth) nextTop = top[1] + 1;
   Bool empty = (top[0]==0);
   Bool full  = (top[1] == -1);

   method Action push(data in);
      rf.upd(nextTop,in);
      top[1] <= nextTop;
   endmethod
   method ActionValue#(data) pop();
      top[0] <= thisTop - 1;
      return rf.sub(thisTop);
   endmethod
   method data peek() = rf.sub(thisTop);
   method Bool notFull() = !full;
   method Bool notEmpty() = !empty;
   method Bit#(TLog#(depth)) remaining() = -1 - thisTop;
endmodule

module mkLF(LF#(data, depth))
   provisos(Log#(depth,logDepth),Bits#(data, data_width));
   LF#(data, depth) lf <- mkUGLF();
   return guardLF(lf);
endmodule

function LF#(data, depth) guardLF (LF#(data, depth) lf) =
   interface LF#(data, depth);
      method Action push(data in) if (lf.notFull);
         lf.push(in);
      endmethod
      method ActionValue#(data) pop() if (lf.notEmpty) = lf.pop();
      method data peek() if (lf.notEmpty) = lf.peek;
      method Bool notFull() = lf.notFull;
      method Bool notEmpty() = lf.notEmpty;
      method Bit#(TLog#(depth)) remaining() = lf.remaining();
   endinterface;