rewrite Gearbox_40_66

rewrite Gearbox_40_66

// Copyright (c) 2014 Cornell University.

// 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.

package Gearbox_40_66;

import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;

interface Gearbox_40_66;
   interface PipeOut#(Bit#(66)) gbOut;
endinterface

module mkGearbox40to66#(PipeOut#(Bit#(40)) pmaOut) (Gearbox_40_66);

   let verbose = False;

   FIFOF#(Bit#(40)) cf <- mkSizedFIFOF(1);
   Vector#(66, Reg#(Bit#(1))) sr0        <- replicateM(mkReg(0));
   Vector#(66, Reg#(Bit#(1))) sr1        <- replicateM(mkReg(0));

   FIFOF#(Bit#(66)) fifo_out <- mkFIFOF;
   PipeOut#(Bit#(66)) pipe_out = toPipeOut(fifo_out);

   Reg#(Bit#(6)) state <- mkReg(0);
   Reg#(Int#(8)) sh_offset <- mkReg(0);
   Reg#(Int#(8)) sh_len    <- mkReg(0);
   Reg#(Bit#(1)) sh_use0   <- mkReg(0);
   Reg#(Bit#(1)) sh_use_sr <- mkReg(0);

   rule state_machine (cf.notEmpty);
      let value = cf.first;
      cf.deq;
      let next_state = state;
      let offset     = sh_offset;
      let len        = sh_len;
      let useSr0     = sh_use0;
      let updateSr   = sh_use_sr;

      case (state)
          32:      next_state = 0;
          default: next_state = next_state + 1;
      endcase

      if (offset + 40 > 66) begin
         len = 66 - offset;
         useSr0 = True;
      end
      else begin
         len = 40;
         useSr0 = False;
      end

      offset = offset + 40;
      if (offset > 66) begin
         offset = offset - 66;
      end

      if (len + sh_offset == 66) begin
         updateSr = True;
      end
      else begin
         updateSr = False;
      end

      Vector#(66, Bit#(1)) sr1_next = unpack(0);
      if (unpack(sh_use0)) begin
         sr1_next = readVReg(sr0);
         $display("state %h: shift sr0 to sr1", state);
      end
      else begin
         sr1_next = readVReg(sr1);
         $display("state %h: keep sr1", state);
      end

      function Bit#(1) value_sub(Integer i);
         Bit#(1) v = 0;
         if (fromInteger(i) < sh_offset) begin
            v = sr1_next[i];
         end
         else if (fromInteger(i) < sh_offset + len) begin
            v = value[fromInteger(i)-sh_offset];
         end
         else begin
            v = sr1_next[i];
         end
         return v;
      endfunction
      Vector#(66, Bit#(1)) next_sr1 = genWith(value_sub);
      writeVReg(take(sr1), next_sr1);

      function Bit#(1) value_sub_sr0(Integer i);
         Bit#(1) v;
         Int#(8) d_start = 40 - len;
         if (updateSr && fromInteger(i) < d_start) begin
            v = value[fromInteger(i) + len];
         end
         else begin
            v = 0;
         end
         return v;
      endfunction
      Vector#(66, Bit#(1)) next_sr0 = genWith(value_sub_sr0);
      writeVReg(take(sr0), next_sr0);

      if (verbose) $display("state %h: curr_sr0=%h next_sr0=%h curr_sr1=%h next_sr1=%h sh_offset=%d len=%d use0=%d update=", state, pack(readVReg(sr0)), pack(next_sr0), pack(readVReg(sr1)), pack(next_sr1), sh_offset, len, sh_use0, updateSr);

      state     <= next_state;
      sh_offset <= offset;
      sh_len    <= len;
      sh_use0   <= pack(useSr0);
      sh_use_sr <= pack(updateSr);

      if (useSr0) begin
         fifo_out.enq(pack(next_sr1));
      end
   endrule

   rule pma_out;
      let v <- toGet(pmaOut).get;
      if(verbose) $display("Rx Pma Out: %h", v);
      cf.enq(v);
   endrule

   interface gbOut = pipe_out;
endmodule

endpackage

//|State |     SR0 (66 bits)           |         SR1 (66 bits)         | Valid | Shift |
//    0    -----------------------------------------[39               0]    0       0
//    1    -------------------[13     0] [65     40][39               0]    1       1
//    2    -------------------------------------[53           14][13  0]    0       0
//    3    ----------------[27        0] [65:54][53           14][13  0]    1       1
//    4    ------------------------[1:0] [65          28][27          0]    1       1
//    5    ----------------------------------------[41           2][1:0]    0       0
//    6    ------------------[15      0] [65    42][41           2][1:0]    1       1
//    7    -------------------------------------[55          16][15   0]    0       0
//    8    -----------------[29       0] [65:56][55          16][15   0]    1       1
//    9    ------------------------[3:0] [65            30][29        0]    1       1
//   10    -------------------------------------[43          4][3     0]    0       0
//   11    --------------    [17      0] [65 44][43          4][3     0]    1       1
//   12    -------------------------------------[58       18][17      0]    0       0
//   13    ----------------[31        0] [65 58][57       18][17      0]    1       1
//   14    ----------------------- [5:0] [65            32][31        0]    1       1
//   15    --------------------------------------[45          6][5    0]    0       0
//   16    ------------------[19      0] [65  46][45          6][5    0]    1       1
//   17    -------------------------------------[59       20][19      0]    0       0
//   18    ----------------[33        0] [65  60][59      20][19      0]    1       1
//   19    ------------------------[7:0] [65        34][33            0]    1       1
//   20    -------------------------------------[47         8][7      0]    0       0
//   21    ------------------[21      0] [65   48][47       8][7      0]    1       1
//   22    ---------------------------------[61      22][21           0]    0       0
//   23    ------------[35            0] [65:62][61  22][21           0]    1       1
//   24    --------------------[9     0] [65      36][35              0]    1       1
//   25    -----------------------------------[49           10][9     0]    0       0
//   26    ------------------[23      0] [65   50][49       10][9     0]    1       1
//   27    ---------------------------------[63         24][23        0]    0       0
//   28    -----------[37             0] [65:64][63     24][23        0]    1       1
//   29    ---------------------[11   0] [65          38][37          0]    1       1
//   30    -----------------------------------[51         12][11      0]    0       0
//   31    ---------------[25         0] [65  52][51      12][11      0]    1       1
//   32    ------------------------------[65           26][25         0]    1       1

// Copyright (c) 2014 Cornell University.

// 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.

package Gearbox_40_66;

import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;

import Pipe::*;
import MemTypes::*;

typedef 33 N_STATE;

interface Gearbox_40_66;
   interface PipeOut#(Bit#(66)) gbOut;
endinterface

(* mutually_exclusive = "state0, state1, state2, state3, state4, state5, state6, state7, state8, state9, state10, state11, state12, state13, state14, state15, state16, state17, state18, state19, state20, state21, state22, state23, state24, state25, state26, state27, state28, state29, state30, state31, state32" *)
module mkGearbox40to66#(PipeOut#(Bit#(40)) pmaOut) (Gearbox_40_66);

   let verbose = False;

   function Bit#(N_STATE) toState(Integer st);
      return 1 << st;
   endfunction

   FIFOF#(Bit#(40)) cf <- mkSizedFIFOF(1);
   Vector#(66, Reg#(Bit#(1))) sr0        <- replicateM(mkReg(0));
   Vector#(66, Reg#(Bit#(1))) sr1        <- replicateM(mkReg(0));

   FIFOF#(Bit#(66)) fifo_out <- mkFIFOF;
   PipeOut#(Bit#(66)) pipe_out = toPipeOut(fifo_out);

   Reg#(Bit#(N_STATE)) state <- mkReg(toState(0));

   function ActionValue#(Vector#(66, Bit#(1))) updateSR1(Bit#(66) reg0, Bit#(66) reg1, Bit#(40) din, Integer offset, Integer len, Bool use0) = actionvalue
      Vector#(66, Bit#(1)) sr = unpack(0);

      if (use0) begin
         sr = unpack(reg0);
      end
      else begin
         sr = unpack(reg1);
      end

      for (Integer idx = offset; idx < offset + len; idx = idx+1) begin
         sr[idx] = din[idx - offset];
      end
      if (verbose) $display("SR1: %h, %h, %h, %h", sr, din, offset, len);
      return sr;
   endactionvalue;

   function ActionValue#(Vector#(66, Bit#(1))) updateSR0(Bit#(40) din, Integer len, Bool update) = actionvalue
      Vector#(66, Bit#(1)) sr = unpack(0);

      if (update) begin
         for (Integer idx = 0; idx < len; idx = idx + 1) begin
            Integer d_start = 40 - len;
            sr[idx] = din[d_start + idx];
         end
      end
      if (verbose) $display("SR0: %h, %h, %h", sr, din, len);
      return sr;
   endactionvalue;

   function ActionValue#(Vector#(66, Bit#(1))) updateSR(Bit#(66) sr0_packed, Bit#(66) sr1_packed, Bit#(40) din, Integer offset, Integer len, Bool use0, Bool update) = actionvalue
      let sr1_next <- updateSR1(sr0_packed, sr1_packed, din, offset, len, use0);
      writeVReg(take(sr1), sr1_next);
      let sr0_next <- updateSR0(din, 40-len, update);
      writeVReg(take(sr0), sr0_next);
      return sr1_next;
   endactionvalue;

   rule state0 (state[0] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 0, 40, False, False);
      state <= toState(1);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state1 (state[1] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 40, 26, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(2);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state2 (state[2] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 14, 40, True, False);
      state <= toState(3);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state3 (state[3] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 54, 12, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(4);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state4 (state[4] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 28, 38, True, True);
      fifo_out.enq(pack(sr));
      state <= toState(5);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state5 (state[5] == 1 && cf.notEmpty);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 2, 40, True, False);
      state <= toState(6);
      if (verbose) $display("state %h: %h", state, pack(sr));
   endrule
   rule state6 (state[6] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 42, 24, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(7);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state7 (state[7] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 16, 40, True, False);
      state <= toState(8);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state8 (state[8] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 56, 10, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(9);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state9 (state[9] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 30, 36, True, True);
      fifo_out.enq(pack(sr));
      state <= toState(10);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state10 (state[10] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 4, 40, True, False);
      state <= toState(11);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state11 (state[11] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 44, 22, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(12);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state12 (state[12] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 18, 40, True, False);
      state <= toState(13);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state13 (state[13] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 58, 8, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(14);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state14 (state[14] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 32, 34, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(15);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state15 (state[15] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 6, 40, True, False);
      state <= toState(16);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state16 (state[16] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 46, 20, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(17);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state17 (state[17] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 20, 40, True, False);
      state <= toState(18);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state18 (state[18] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 60, 6, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(19);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state19 (state[19] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 34, 32, True, True);
      fifo_out.enq(pack(sr));
      state <= toState(20);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state20 (state[20] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 8, 40, True, False);
      state <= toState(21);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state21 (state[21] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 48, 18, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(22);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state22 (state[22] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 22, 40, True, False);
      state <= toState(23);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state23 (state[23] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 62, 4, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(24);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state24 (state[24] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 36, 30, True, True);
      fifo_out.enq(pack(sr));
      state <= toState(25);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state25 (state[25] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 10, 40, True, False);
      state <= toState(26);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state26 (state[26] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 50, 16, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(27);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state27 (state[27] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 24, 40, True, False);
      state <= toState(28);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state28 (state[28] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 64, 2, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(29);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state29 (state[29] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 38, 28, True, True);
      fifo_out.enq(pack(sr));
      state <= toState(30);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state30 (state[30] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 12, 40, True, False);
      state <= toState(31);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state31 (state[31] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 52, 14, False, True);
      fifo_out.enq(pack(sr));
      state <= toState(32);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule
   rule state32 (state[32] == 1);
      let value = cf.first();
      cf.deq;
      let sr <- updateSR(pack(readVReg(sr0)), pack(readVReg(sr1)), value, 26, 40, True, False);
      fifo_out.enq(pack(sr));
      state <= toState(0);
      if (verbose) $display("state %h: %h, %h", state, readVReg(sr0), readVReg(sr1));
   endrule

   rule pma_out;
      let v <- toGet(pmaOut).get;
      //if(verbose) $display("Rx Pma Out: %h", v);
      cf.enq(v);
   endrule

   interface gbOut = pipe_out;
endmodule

endpackage

//|State |     SR0 (66 bits)           |         SR1 (66 bits)         | Valid | Shift |
//    0    -----------------------------------------[39               0]    0       0
//    1    -------------------[13     0] [65     40][39               0]    1       1
//    2    -------------------------------------[53           14][13  0]    0       0
//    3    ----------------[27        0] [65:54][53           14][13  0]    1       1
//    4    ------------------------[1:0] [65          28][27          0]    1       1
//    5    ----------------------------------------[41           2][1:0]    0       0
//    6    ------------------[15      0] [65    42][41           2][1:0]    1       1
//    7    -------------------------------------[55          16][15   0]    0       0
//    8    -----------------[29       0] [65:56][55          16][15   0]    1       1
//    9    ------------------------[3:0] [65            30][29        0]    1       1
//   10    -------------------------------------[43          4][3     0]    0       0
//   11    --------------    [17      0] [65 44][43          4][3     0]    1       1
//   12    -------------------------------------[58       18][17      0]    0       0
//   13    ----------------[31        0] [65 58][57       18][17      0]    1       1
//   14    ----------------------- [5:0] [65            32][31        0]    1       1
//   15    --------------------------------------[45          6][5    0]    0       0
//   16    ------------------[19      0] [65  46][45          6][5    0]    1       1
//   17    -------------------------------------[59       20][19      0]    0       0
//   18    ----------------[33        0] [65  60][59      20][19      0]    1       1
//   19    ------------------------[7:0] [65        34][33            0]    1       1
//   20    -------------------------------------[47         8][7      0]    0       0
//   21    ------------------[21      0] [65   48][47       8][7      0]    1       1
//   22    ---------------------------------[61      22][21           0]    0       0
//   23    ------------[35            0] [65:62][61  22][21           0]    1       1
//   24    --------------------[9     0] [65      36][35              0]    1       1
//   25    -----------------------------------[49           10][9     0]    0       0
//   26    ------------------[23      0] [65   50][49       10][9     0]    1       1
//   27    ---------------------------------[63         24][23        0]    0       0
//   28    -----------[37             0] [65:64][63     24][23        0]    1       1
//   29    ---------------------[11   0] [65          38][37          0]    1       1
//   30    -----------------------------------[51         12][11      0]    0       0
//   31    ---------------[25         0] [65  52][51      12][11      0]    1       1
//   32    ------------------------------[65           26][25         0]    1       1


Add RV32 support for RVMulDiv

Add RV32 support for RVMulDiv

// Copyright (c) 2016 Massachusetts Institute of Technology

// 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.

`include "ProcConfig.bsv"
// MulDiv.bsv
// This file contains modules needed for hardware multiplication and division.
// The MulDivExec module abstracts away the ISA implementation simplifying the
// requirements for the hardware multiplier and divider. Multiplier and
// Divider are just a multiplier and a divider that do 65-bit signed math.
// All other details of the ISA is handled in MulDivExec.

import RVTypes::*;
import FIFOF::*;

// Functions for easily checking things about muldiv instructions
function Bool isMul(MulDivFunc func);
  return (case(func)
    Mul, Mulh: True;
    default: False;
  endcase);
endfunction
function Bool isDiv(MulDivFunc func);
  return (case(func)
    Div, Rem: True;
    default: False;
  endcase);
endfunction

interface Multiplier;
  // input
  method Action               multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier);
  // output
  method Bool                 result_rdy;
  method Tuple2#(Data, Data)  result_data;
  method Action               result_deq;
endinterface

interface Divider;
  // input
  method Action               divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor);
  // output
  method Bool                 result_rdy;
  method Tuple2#(Data, Data)  result_data;
  method Action               result_deq;
endinterface

// This module takes in the same operands as exec
interface MulDivExec;
    method Action   exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    method Bool     notEmpty; // True if there is any instruction in this pipeline
    // output
    method Bool     result_rdy;
    method Data     result_data;
    method Action   result_deq;
endinterface

(* synthesize *)
module mkBluesimMultiplier(Multiplier);
  FIFOF#(Tuple2#(Data, Data)) result_fifo <- mkSizedFIFOF(4);

  method Action multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier);
    Int#(TAdd#(TAdd#(DataSz, DataSz), 1)) a = unpack(signExtend(multiplicand));
    Int#(TAdd#(TAdd#(DataSz, DataSz), 1)) b = unpack(signExtend(multiplier));

    // This is a 65-bit signed multiplication
    // FIXME: Replace this with an efficient multiplication implementation like a booth multiplier
    Bit#(TAdd#(TAdd#(DataSz, DataSz), 1)) r = pack(a * b);

    Tuple2#(Data, Data) answer = tuple2( r[2*valueOf(DataSz)-1:valueOf(DataSz)], r[valueOf(DataSz)-1:0] );
    result_fifo.enq(answer);
  endmethod

  method Bool result_rdy = result_fifo.notEmpty;
  method Tuple2#(Data, Data) result_data = result_fifo.first;
  method Action result_deq = result_fifo.deq;
endmodule

// This is a radix-4 Booth multiplier was taken from the 6.175 Lab
(* synthesize *)
module mkBoothMultiplier(Multiplier)
    provisos (
      NumAlias#(TAdd#(DataSz, 2),                         _InputSize), // This _could_ be DataSz+1 if we tried harder
      NumAlias#(TAdd#(TAdd#(_InputSize, _InputSize), 2),  _MultSize),
      NumAlias#(TAdd#(TLog#(_InputSize), 1),              _IndexSize)
    );
  Reg#(Bit#(_MultSize)) m_neg <- mkReg(0);
  Reg#(Bit#(_MultSize)) m_pos <- mkReg(0);
  Reg#(Bit#(_MultSize)) p <- mkReg(0);
  Reg#(Bit#(_IndexSize)) i <- mkReg(fromInteger(valueOf(_InputSize)/2+1));

  rule mul_step( i < fromInteger(valueOf(_InputSize)/2) );
    let pr = p[2:0];
    Int#(_MultSize) new_p = unpack(p);
    case (pr)
      3'b001: new_p = new_p + unpack(m_pos);
      3'b010: new_p = new_p + unpack(m_pos);
      3'b011: new_p = new_p + unpack(m_pos << 1);
      3'b100: new_p = new_p + unpack(m_neg << 1);
      3'b101: new_p = new_p + unpack(m_neg);
      3'b110: new_p = new_p + unpack(m_neg);
    endcase
    new_p = new_p >> 2;
    p <= pack(new_p);
    i <= i+1;
  endrule

  method Action multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier) if (i == fromInteger(valueOf(_InputSize)/2+1));
    Bit#(_InputSize) x = signExtend(multiplicand);
    Bit#(_InputSize) y = signExtend(multiplier);
    m_pos <= {msb(x), x, 0};
    m_neg <= {msb(-x), -x, 0};
    p <= {0, y, 1'b0};
    i <= 0;
  endmethod

  method Bool result_rdy;
    return i == fromInteger(valueOf(_InputSize)/2);
  endmethod
  method Tuple2#(Data, Data) result_data if (i == fromInteger(valueOf(_InputSize)/2));
    // was: return tuple2(p[128:65], p[64:1]);
    return tuple2(p[2*valueOf(DataSz):valueOf(DataSz)+1], p[valueOf(DataSz):1]);
  endmethod
  method Action result_deq if (i == fromInteger(valueOf(_InputSize)/2));
    i <= fromInteger(valueOf(_InputSize)/2+1);
  endmethod
endmodule

(* synthesize *)
module mkBluesimDivider(Divider);
  FIFOF#(Tuple2#(Data, Data)) result_fifo <- mkSizedFIFOF(4);

  method Action divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor);
    // This is a 65-bit signed division
    // FIXME: Replace this with an efficient division implementation
    // Bluesim causes a runtime error when dividing by zero, even if the
    // division is part of an unused part of a ternary operation. To avoid
    // this we change the divisor to 1 if it is zero.
    Int#(TAdd#(DataSz, 1)) quotent = (divisor != 0) ? (unpack(dividend) / ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack('1);
    Int#(TAdd#(DataSz, 1)) remainder = (divisor != 0) ? (unpack(dividend) % ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack(dividend);

    if ((dividend == {2'b11, 0}) && (divisor == '1)) begin
      quotent = unpack(dividend);
      remainder = 0;
    end
    result_fifo.enq(tuple2(truncate(pack(quotent)), truncate(pack(remainder))));
  endmethod

  method Bool result_rdy = result_fifo.notEmpty;
  method Tuple2#(Data, Data) result_data = result_fifo.first;
  method Action result_deq = result_fifo.deq;
endmodule

(* synthesize *)
module mkRoughDivider(Divider)
    provisos (
      NumAlias#(TAdd#(DataSz, 1),               _InputSize),
      NumAlias#(TAdd#(_InputSize, _InputSize),  _DivSize),
      NumAlias#(TAdd#(TLog#(_InputSize), 2),    _IndexSize)
    );
  // These are probably bigger than needed. This isn't called a rough divider for nothing
  Reg#(Int#(_DivSize)) remainder <- mkReg(0);
  Reg#(Int#(_DivSize)) quotent <- mkReg(0);
  Reg#(Int#(_DivSize)) divisor_reg <- mkReg(0);
  Reg#(Bit#(_IndexSize)) current_bit <- mkReg(fromInteger(valueOf(_InputSize) + 1));
  Reg#(Bool) quotent_negative <- mkReg(False);
  Reg#(Bool) remainder_negative <- mkReg(False);

  rule doBit(current_bit < fromInteger(valueOf(_InputSize)));
    // add if doesn't change sign
    let tmp_remainder = remainder - (divisor_reg << current_bit);
    if ((((divisor_reg << current_bit) >> current_bit) == divisor_reg) && (msb(tmp_remainder) == 0)) begin
      // it divides!
      remainder <= tmp_remainder;
      quotent <= quotent | (1 << current_bit);
    end
    current_bit <= (current_bit == 0) ? fromInteger(valueOf(_InputSize)) : current_bit - 1;
  endrule

  method Action divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor) if (current_bit == fromInteger(valueOf(_InputSize) + 1));
    // Optimization: Divide by zero and handle signed overflow very fast
    if ((dividend == {2'b11, 0}) && (divisor == '1)) begin
      quotent <= unpack(signExtend(dividend));
      remainder <= 0;
      quotent_negative <= False;
      remainder_negative <= False;
      current_bit <= fromInteger(valueOf(_InputSize));
    end else if (divisor == 0) begin
      quotent <= unpack('1);
      remainder <= unpack(signExtend(dividend));
      quotent_negative <= False;
      remainder_negative <= False;
      current_bit <= fromInteger(valueOf(_InputSize));
    end else begin
      // Lets make everything positive because I can't think about signed division right now
      Bool top_negative = (msb(dividend) == 1);
      Bool bottom_negative = (msb(divisor) == 1);

      quotent <= 0;

      if (top_negative)
        remainder <= -unpack(signExtend(dividend));
      else
        remainder <= unpack(signExtend(dividend));

      if (bottom_negative)
        divisor_reg <= -unpack(signExtend(divisor));
      else
        divisor_reg <= unpack(signExtend(divisor));

      quotent_negative <= (top_negative != bottom_negative);
      remainder_negative <= top_negative;

      Int#(TAdd#(DataSz, 1)) quotent = (divisor != 0) ? (unpack(dividend) / ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack('1);
      Int#(TAdd#(DataSz, 1)) remainder = (divisor != 0) ? (unpack(dividend) % ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack(dividend);

      current_bit <= fromInteger(valueOf(_InputSize)-1);
    end
  endmethod

  method Bool result_rdy;
    return (current_bit == fromInteger(valueOf(_InputSize)));
  endmethod
  method Tuple2#(Data, Data) result_data if (current_bit == fromInteger(valueOf(_InputSize)));
    Int#(_DivSize) final_quotent = quotent_negative ? -quotent : quotent;
    Int#(_DivSize) final_remainder = remainder_negative ? -remainder : remainder;
    return tuple2(truncate(pack(final_quotent)), truncate(pack(final_remainder)));
  endmethod
  method Action result_deq if (current_bit == fromInteger(valueOf(_InputSize)));
    current_bit <= fromInteger(valueOf(_InputSize) + 1);
  endmethod
endmodule

module mkMulDivExec#(Multiplier mul_unit, Divider div_unit)(MulDivExec);
  Bool verbose = False;

  // This fifo holds what operation is being done by the unit
  // If the value is invalid, then the result is already in muldiv_exec_fifo
  FIFOF#(MulDivInst) func_fifo <- mkFIFOF;

  method Action exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    if (verbose) $display("[MulDiv] ", fshow(mdInst), ", ", fshow(rVal1), ", ", fshow(rVal2) );

    Bit#(TAdd#(DataSz, 1)) a = 0;
    Bit#(TAdd#(DataSz, 1)) b = 0;
    case (mdInst.sign)
      Signed: begin
        a = signExtend(rVal1);
        b = signExtend(rVal2);
      end
      Unsigned: begin
        a = zeroExtend(rVal1);
        b = zeroExtend(rVal2);
      end
      SignedUnsigned: begin
        a = signExtend(rVal1);
        b = zeroExtend(rVal2);
      end
    endcase

    case (mdInst.func)
      Mul, Mulh : mul_unit.multiply(a, b);
      Div, Rem  : div_unit.divide(a, b);
    endcase

    func_fifo.enq(mdInst);
  endmethod

  method Bool notEmpty = func_fifo.notEmpty;

  // output
  method Bool result_rdy;
    return (isMul(func_fifo.first.func)) ? mul_unit.result_rdy : div_unit.result_rdy;
  endmethod
  method Data result_data;
    let mdInst = func_fifo.first;
    Data data = (case(mdInst.func)
        Mul  : tpl_2(mul_unit.result_data);
        Mulh : tpl_1(mul_unit.result_data);
        Div  : tpl_1(div_unit.result_data);
        Rem  : tpl_2(div_unit.result_data);
      endcase);
    // correct for w instructions
    if (mdInst.w) begin
      data = signExtend(data[31:0]);
    end
    return data;
  endmethod
  method Action result_deq;
    let mdInst = func_fifo.first;

    // For debugging
    // This can't be included in the above method because it is not an Action
    if (verbose) begin
      Data data = (case(mdInst.func)
          Mul  : tpl_2(mul_unit.result_data);
          Mulh : tpl_1(mul_unit.result_data);
          Div  : tpl_1(div_unit.result_data);
          Rem  : tpl_2(div_unit.result_data);
        endcase);
      // correct for w instructions
      if (mdInst.w) begin
        data = signExtend(data[31:0]);
      end
      $display("[MulDiv] result: ", fshow(data));
    end

    // Actual action
    func_fifo.deq;
    case (mdInst.func)
      Mul, Mulh : mul_unit.result_deq;
      Div, Rem  : div_unit.result_deq;
    endcase
  endmethod
endmodule

(* synthesize *)
module mkBluesimMulDivExec(MulDivExec);
  Multiplier mul_unit <- mkBluesimMultiplier;
  Divider div_unit <- mkBluesimDivider;
  MulDivExec ifc <- mkMulDivExec(mul_unit, div_unit);
  return ifc;
endmodule

(* synthesize *)
module mkBoothRoughMulDivExec(MulDivExec);
  Multiplier mul_unit <- mkBoothMultiplier;
  Divider div_unit <- mkRoughDivider;
  MulDivExec ifc <- mkMulDivExec(mul_unit, div_unit);
  return ifc;
endmodule

(* synthesize *)
module mkMulDivExecDummy(MulDivExec);
  FIFOF#(Data) muldiv_exec_fifo <- mkFIFOF;

  method Action exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    $fdisplay(stderr, "[ERROR] mkMulDivExecDummy is in use");
    Data res = 0;
    muldiv_exec_fifo.enq(res);
  endmethod

  method Bool notEmpty = muldiv_exec_fifo.notEmpty;

  // output
  method Bool result_rdy = muldiv_exec_fifo.notEmpty;
  method Data result_data = muldiv_exec_fifo.first;
  method Action result_deq = muldiv_exec_fifo.deq;
endmodule

// Copyright (c) 2016 Massachusetts Institute of Technology

// 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.

`include "ProcConfig.bsv"
// MulDiv.bsv
// This file contains modules needed for hardware multiplication and division.
// The MulDivExec module abstracts away the ISA implementation simplifying the
// requirements for the hardware multiplier and divider. Multiplier and
// Divider are just a multiplier and a divider that do 65-bit signed math.
// All other details of the ISA is handled in MulDivExec.

import RVTypes::*;
import FIFOF::*;

// Functions for easily checking things about muldiv instructions
function Bool isMul(MulDivFunc func);
  return (case(func)
    Mul, Mulh: True;
    default: False;
  endcase);
endfunction
function Bool isDiv(MulDivFunc func);
  return (case(func)
    Div, Rem: True;
    default: False;
  endcase);
endfunction

interface Multiplier;
  // input
  method Action               multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier);
  // output
  method Bool                 result_rdy;
  method Tuple2#(Data, Data)  result_data;
  method Action               result_deq;
endinterface

interface Divider;
  // input
  method Action               divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor);
  // output
  method Bool                 result_rdy;
  method Tuple2#(Data, Data)  result_data;
  method Action               result_deq;
endinterface

// This module takes in the same operands as exec
interface MulDivExec;
    method Action   exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    method Bool     notEmpty; // True if there is any instruction in this pipeline
    // output
    method Bool     result_rdy;
    method Data     result_data;
    method Action   result_deq;
endinterface

(* synthesize *)
module mkBluesimMultiplier(Multiplier);
  FIFOF#(Tuple2#(Data, Data)) result_fifo <- mkSizedFIFOF(4);

  method Action multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier);
    Int#(TAdd#(TAdd#(DataSz, DataSz), 1)) a = unpack(signExtend(multiplicand));
    Int#(TAdd#(TAdd#(DataSz, DataSz), 1)) b = unpack(signExtend(multiplier));

    // This is a 65-bit signed multiplication
    // FIXME: Replace this with an efficient multiplication implementation like a booth multiplier
    Bit#(TAdd#(TAdd#(DataSz, DataSz), 1)) r = pack(a * b);

    Tuple2#(Data, Data) answer = tuple2( r[127:64], r[63:0] );
    result_fifo.enq(answer);
  endmethod

  method Bool result_rdy = result_fifo.notEmpty;
  method Tuple2#(Data, Data) result_data = result_fifo.first;
  method Action result_deq = result_fifo.deq;
endmodule

// This is a radix-4 Booth multiplier was taken from the 6.175 Lab
(* synthesize *)
module mkBoothMultiplier(Multiplier)
    provisos (
      NumAlias#(TAdd#(DataSz, 2),                         _InputSize), // This _could_ be DataSz+1 if we tried harder
      NumAlias#(TAdd#(TAdd#(_InputSize, _InputSize), 2),  _MultSize),
      NumAlias#(TAdd#(TLog#(_InputSize), 1),              _IndexSize)
    );
  Reg#(Bit#(_MultSize)) m_neg <- mkReg(0);
  Reg#(Bit#(_MultSize)) m_pos <- mkReg(0);
  Reg#(Bit#(_MultSize)) p <- mkReg(0);
  Reg#(Bit#(_IndexSize)) i <- mkReg(fromInteger(valueOf(_InputSize)/2+1));

  rule mul_step( i < fromInteger(valueOf(_InputSize)/2) );
    let pr = p[2:0];
    Int#(_MultSize) new_p = unpack(p);
    case (pr)
      3'b001: new_p = new_p + unpack(m_pos);
      3'b010: new_p = new_p + unpack(m_pos);
      3'b011: new_p = new_p + unpack(m_pos << 1);
      3'b100: new_p = new_p + unpack(m_neg << 1);
      3'b101: new_p = new_p + unpack(m_neg);
      3'b110: new_p = new_p + unpack(m_neg);
    endcase
    new_p = new_p >> 2;
    p <= pack(new_p);
    i <= i+1;
  endrule

  method Action multiply(Bit#(TAdd#(DataSz, 1)) multiplicand, Bit#(TAdd#(DataSz, 1)) multiplier) if (i == fromInteger(valueOf(_InputSize)/2+1));
    Bit#(_InputSize) x = signExtend(multiplicand);
    Bit#(_InputSize) y = signExtend(multiplier);
    m_pos <= {msb(x), x, 0};
    m_neg <= {msb(-x), -x, 0};
    p <= {0, y, 1'b0};
    i <= 0;
  endmethod

  method Bool result_rdy;
    return i == fromInteger(valueOf(_InputSize)/2);
  endmethod
  method Tuple2#(Data, Data) result_data if (i == fromInteger(valueOf(_InputSize)/2));
    return tuple2(p[128:65], p[64:1]);
  endmethod
  method Action result_deq if (i == fromInteger(valueOf(_InputSize)/2));
    i <= fromInteger(valueOf(_InputSize)/2+1);
  endmethod
endmodule

(* synthesize *)
module mkBluesimDivider(Divider);
  FIFOF#(Tuple2#(Data, Data)) result_fifo <- mkSizedFIFOF(4);

  method Action divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor);
    // This is a 65-bit signed division
    // FIXME: Replace this with an efficient division implementation
    // Bluesim causes a runtime error when dividing by zero, even if the
    // division is part of an unused part of a ternary operation. To avoid
    // this we change the divisor to 1 if it is zero.
    Int#(TAdd#(DataSz, 1)) quotent = (divisor != 0) ? (unpack(dividend) / ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack('1);
    Int#(TAdd#(DataSz, 1)) remainder = (divisor != 0) ? (unpack(dividend) % ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack(dividend);

    if ((dividend == 65'h18000000000000000) && (divisor == '1)) begin
      quotent = unpack(dividend);
      remainder = 0;
    end
    result_fifo.enq(tuple2(truncate(pack(quotent)), truncate(pack(remainder))));
  endmethod

  method Bool result_rdy = result_fifo.notEmpty;
  method Tuple2#(Data, Data) result_data = result_fifo.first;
  method Action result_deq = result_fifo.deq;
endmodule

(* synthesize *)
module mkRoughDivider(Divider)
    provisos (
      NumAlias#(TAdd#(DataSz, 1),               _InputSize),
      NumAlias#(TAdd#(_InputSize, _InputSize),  _DivSize),
      NumAlias#(TAdd#(TLog#(_InputSize), 2),    _IndexSize)
    );
  // These are probably bigger than needed. This isn't called a rough divider for nothing
  Reg#(Int#(_DivSize)) remainder <- mkReg(0);
  Reg#(Int#(_DivSize)) quotent <- mkReg(0);
  Reg#(Int#(_DivSize)) divisor_reg <- mkReg(0);
  Reg#(Bit#(_IndexSize)) current_bit <- mkReg(fromInteger(valueOf(_InputSize) + 1));
  Reg#(Bool) quotent_negative <- mkReg(False);
  Reg#(Bool) remainder_negative <- mkReg(False);

  rule doBit(current_bit < fromInteger(valueOf(_InputSize)));
    // add if doesn't change sign
    let tmp_remainder = remainder - (divisor_reg << current_bit);
    if ((((divisor_reg << current_bit) >> current_bit) == divisor_reg) && (msb(tmp_remainder) == 0)) begin
      // it divides!
      remainder <= tmp_remainder;
      quotent <= quotent | (1 << current_bit);
    end
    current_bit <= (current_bit == 0) ? fromInteger(valueOf(_InputSize)) : current_bit - 1;
  endrule

  method Action divide(Bit#(TAdd#(DataSz, 1)) dividend, Bit#(TAdd#(DataSz, 1)) divisor) if (current_bit == fromInteger(valueOf(_InputSize) + 1));
    // Optimization: Divide by zero and handle signed overflow very fast
    if ((dividend == 65'h18000000000000000) && (divisor == '1)) begin
      quotent <= unpack(signExtend(dividend));
      remainder <= 0;
      quotent_negative <= False;
      remainder_negative <= False;
      current_bit <= fromInteger(valueOf(_InputSize));
    end else if (divisor == 0) begin
      quotent <= unpack('1);
      remainder <= unpack(signExtend(dividend));
      quotent_negative <= False;
      remainder_negative <= False;
      current_bit <= fromInteger(valueOf(_InputSize));
    end else begin
      // Lets make everything positive because I can't think about signed division right now
      Bool top_negative = (msb(dividend) == 1);
      Bool bottom_negative = (msb(divisor) == 1);

      quotent <= 0;

      if (top_negative)
        remainder <= -unpack(signExtend(dividend));
      else
        remainder <= unpack(signExtend(dividend));

      if (bottom_negative)
        divisor_reg <= -unpack(signExtend(divisor));
      else
        divisor_reg <= unpack(signExtend(divisor));

      quotent_negative <= (top_negative != bottom_negative);
      remainder_negative <= top_negative;

      Int#(TAdd#(DataSz, 1)) quotent = (divisor != 0) ? (unpack(dividend) / ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack('1);
      Int#(TAdd#(DataSz, 1)) remainder = (divisor != 0) ? (unpack(dividend) % ((divisor != 0) ? unpack(divisor) : unpack(1))) : unpack(dividend);

      current_bit <= fromInteger(valueOf(_InputSize)-1);
    end
  endmethod

  method Bool result_rdy;
    return (current_bit == fromInteger(valueOf(_InputSize)));
  endmethod
  method Tuple2#(Data, Data) result_data if (current_bit == fromInteger(valueOf(_InputSize)));
    Int#(_DivSize) final_quotent = quotent_negative ? -quotent : quotent;
    Int#(_DivSize) final_remainder = remainder_negative ? -remainder : remainder;
    return tuple2(truncate(pack(final_quotent)), truncate(pack(final_remainder)));
  endmethod
  method Action result_deq if (current_bit == fromInteger(valueOf(_InputSize)));
    current_bit <= fromInteger(valueOf(_InputSize) + 1);
  endmethod
endmodule

module mkMulDivExec#(Multiplier mul_unit, Divider div_unit)(MulDivExec);
  Bool verbose = False;

  // This fifo holds what operation is being done by the unit
  // If the value is invalid, then the result is already in muldiv_exec_fifo
  FIFOF#(MulDivInst) func_fifo <- mkFIFOF;

  method Action exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    if (verbose) $display("[MulDiv] ", fshow(mdInst), ", ", fshow(rVal1), ", ", fshow(rVal2) );

    Bit#(TAdd#(DataSz, 1)) a = 0;
    Bit#(TAdd#(DataSz, 1)) b = 0;
    case (mdInst.sign)
      Signed: begin
        a = signExtend(rVal1);
        b = signExtend(rVal2);
      end
      Unsigned: begin
        a = zeroExtend(rVal1);
        b = zeroExtend(rVal2);
      end
      SignedUnsigned: begin
        a = signExtend(rVal1);
        b = zeroExtend(rVal2);
      end
    endcase

    case (mdInst.func)
      Mul, Mulh : mul_unit.multiply(a, b);
      Div, Rem  : div_unit.divide(a, b);
    endcase

    func_fifo.enq(mdInst);
  endmethod

  method Bool notEmpty = func_fifo.notEmpty;

  // output
  method Bool result_rdy;
    return (isMul(func_fifo.first.func)) ? mul_unit.result_rdy : div_unit.result_rdy;
  endmethod
  method Data result_data;
    let mdInst = func_fifo.first;
    Data data = (case(mdInst.func)
        Mul  : tpl_2(mul_unit.result_data);
        Mulh : tpl_1(mul_unit.result_data);
        Div  : tpl_1(div_unit.result_data);
        Rem  : tpl_2(div_unit.result_data);
      endcase);
    // correct for w instructions
    if (mdInst.w) begin
      data = signExtend(data[31:0]);
    end
    return data;
  endmethod
  method Action result_deq;
    let mdInst = func_fifo.first;

    // For debugging
    // This can't be included in the above method because it is not an Action
    if (verbose) begin
      Data data = (case(mdInst.func)
          Mul  : tpl_2(mul_unit.result_data);
          Mulh : tpl_1(mul_unit.result_data);
          Div  : tpl_1(div_unit.result_data);
          Rem  : tpl_2(div_unit.result_data);
        endcase);
      // correct for w instructions
      if (mdInst.w) begin
        data = signExtend(data[31:0]);
      end
      $display("[MulDiv] result: ", fshow(data));
    end

    // Actual action
    func_fifo.deq;
    case (mdInst.func)
      Mul, Mulh : mul_unit.result_deq;
      Div, Rem  : div_unit.result_deq;
    endcase
  endmethod
endmodule

(* synthesize *)
module mkBluesimMulDivExec(MulDivExec);
  Multiplier mul_unit <- mkBluesimMultiplier;
  Divider div_unit <- mkBluesimDivider;
  MulDivExec ifc <- mkMulDivExec(mul_unit, div_unit);
  return ifc;
endmodule

(* synthesize *)
module mkBoothRoughMulDivExec(MulDivExec);
  Multiplier mul_unit <- mkBoothMultiplier;
  Divider div_unit <- mkRoughDivider;
  MulDivExec ifc <- mkMulDivExec(mul_unit, div_unit);
  return ifc;
endmodule

(* synthesize *)
module mkMulDivExecDummy(MulDivExec);
  FIFOF#(Data) muldiv_exec_fifo <- mkFIFOF;

  method Action exec(MulDivInst mdInst, Data rVal1, Data rVal2);
    $fdisplay(stderr, "[ERROR] mkMulDivExecDummy is in use");
    Data res = 0;
    muldiv_exec_fifo.enq(res);
  endmethod

  method Bool notEmpty = muldiv_exec_fifo.notEmpty;

  // output
  method Bool result_rdy = muldiv_exec_fifo.notEmpty;
  method Data result_data = muldiv_exec_fifo.first;
  method Action result_deq = muldiv_exec_fifo.deq;
endmodule


refactor

refactor

// 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 Clocks       :: *;
import DefaultValue :: *;
import XilinxCells  :: *;
import Vector       :: *;

(* always_ready, always_enabled *)
interface Bidir#(DATA_WIDTH);
    method Action            i(Bit#(DATA_WIDTH) v);
    method Bit#(DATA_WIDTH)  o();
    method Bit#(DATA_WIDTH)  t();
endinterface
typedef struct {
    Bit#(32)                 addr;
    Bit#(2)                  burst;
    Bit#(4)                  cache;
    Bit#(ID_WIDTH)           id;
    Bit#(4)                  len;
    Bit#(2)                  lock;
    Bit#(3)                  prot;
    Bit#(4)                  qos;
    Bit#(3)                  size;
    Bit#(1)                  valid;
} AxiREQ#(numeric type ID_WIDTH);
typedef struct {
    AxiREQ                   ar;
    AxiREQ                   aw;
    Bit#(1)                  bready;
    Bit#(1)                  rready;
    Bit#(DATA_WIDTH)         wdata;
    Bit#(ID_WIDTH)           wid;
    Bit#(1)                  wlast;
    Bit#(DATA_WIDTH/8)       wstrb;
    Bit#(1)                  wvalid;
} AxiMOSI#(numeric type DATA_WIDTH, numeric type ID_WIDTH);
typedef struct {
    Bit#(ID_WIDTH)           id;
    Bit#(2)                  resp;
    Bit#(1)                  valid;
} AxiVALID#(numeric type ID_WIDTH);
typedef struct {
    Bit#(1)                  arready;
    Bit#(1)                  awready;
    AxiVALID#(DATA_WIDTH, ID_WIDTH) b;
    AxiVALID#(DATA_WIDTH, ID_WIDTH) r;
    Bit#(DATA_WIDTH)         rdata;
    Bit#(1)                  rlast;
    Bit#(1)                  wready;
} AxiMISO(numeric type DATA_WIDTH, numeric type ID_WIDTH);

interface AxiMasterCommon#(numeric type DATA_WIDTH, numeric type ID_WIDTH);
    method Action            aclk(Bit#(1) v); // common
    method Bit#(1)           aresetn();      // common
    AxiMOSI#(DATA_WIDTH, ID_WIDTH);
    AxiMISO#(DATA_WIDTH, ID_WIDTH);
    method Action            araddr(Bit#(32) v);
    method Bit#(1)           arready();
endinterface

interface AxiSlaveCommon#(numeric type DATA_WIDTH, numeric type ID_WIDTH);
    method Action            aclk(Bit#(1) v); // common
    method Bit#(1)           aresetn();      // common
    AxiMOSI#(DATA_WIDTH, ID_WIDTH);
    AxiMISO#(DATA_WIDTH, ID_WIDTH);
    method Action            araddr(Bit#(32) v);
    method Bit#(1)           arready();
endinterface

interface AxiSlaveHighSpeed#(numeric type DATA_WIDTH, numeric type ID_WIDTH);
    interface AxiCommon#(DATA_WIDTH, ID_WIDTH) axi;
    method Bit#(3)           racount();
    method Bit#(8)           rcount();
    method Action            rdissuecap1_en(Bit#(1) v);
    method Bit#(6)           wacount();
    method Bit#(8)           wcount();
    method Action            wrissuecap1_en(Bit#(1) v);
endinterface
interface Ddr;
    method Action            arb(Bit#(4) v);
    method Bit#(15)          addr();
    method Bit#(3)           bankaddr();
    method Bit#(1)           cas_n();
    method Bit#(1)           cke();
    method Bit#(1)           cs_n();
    method Bit#(1)           clk();
    method Bit#(1)           clk_n();
    method Bit#(DM_WIDTH)    dm();
    method Bit#(DQ_WIDTH)    dq();
    method Bit#(DQS_WIDTH) dqs();
    method Bit#(DQS_WIDTH) dqs_n();
    method Bit#(1)           drstb();
    method Bit#(1)           odt();
    method Bit#(1)           ras_n();
    method Bit#(1)           vrn();
    method Bit#(1)           vrp();
    method Bit#(1)           web();
endinterface
interface Dma;
    method Action            aclk(Bit#(1) v);
    method Action            daready(Bit#(1) v);
    method Bit#(2)           datype();
    method Bit#(1)           davalid();
    method Action            drlast(Bit#(1) v);
    method Bit#(1)           drready();
    method Action            drtype(Bit#(2) v);
    method Action            drvalid(Bit#(1) v);
    method Bit#(1)           rstn();
endinterface
interface Enet;
    method Action            ext_intin(Bit#(1) v);
    method Action            gmii_col(Bit#(1) v);
    method Action            gmii_crs(Bit#(1) v);
    method Action            gmii_rxd(Bit#(8) v);
    method Action            gmii_rx_clk(Bit#(1) v);
    method Action            gmii_rx_dv(Bit#(1) v);
    method Action            gmii_rx_er(Bit#(1) v);
    method Bit#(8)           gmii_txd();
    method Action            gmii_tx_clk(Bit#(1) v);
    method Bit#(1)           gmii_tx_en();
    method Bit#(1)           gmii_tx_er();
    method Bit#(1)           mdio_mdc();
    interface Bidir(1)       mdio;
    method Bit#(1)           ptp_delay_req_rx();
    method Bit#(1)           ptp_delay_req_tx();
    method Bit#(1)           ptp_pdelay_req_rx();
    method Bit#(1)           ptp_pdelay_req_tx();
    method Bit#(1)           ptp_pdelay_resp_rx();
    method Bit#(1)           ptp_pdelay_resp_tx();
    method Bit#(1)           ptp_sync_frame_rx();
    method Bit#(1)           ptp_sync_frame_tx();
    method Bit#(1)           sof_rx();
    method Bit#(1)           sof_tx();
endinterface
interface Sdio;
    method Bit#(1)           buspow();
    method Bit#(3)           busvolt();
    method Action            cdn(Bit#(1) v);
    method Bit#(1)           clk();
    method Action            clk_fb(Bit#(1) v);
    interface Bidir(1)       cmd;
    interface Bidir(4)       data;
    method Bit#(1)           led();
    method Action            wp(Bit#(1) v);
endinterface
interface Spi;
    interface Bidir(1)       miso;
    interface Bidir(1)       mosi;
    interface Bidir(1)       sclk;
    method Bit#(1)           ss1_o();
    method Bit#(1)           ss2_o();
    interface Bidir(1)       ss;
endinterface
interface Ttc;
    method Action            clk0_in(Bit#(1) v);
    method Action            clk1_in(Bit#(1) v);
    method Action            clk2_in(Bit#(1) v);
    method Bit#(1)           wave0_out();
    method Bit#(1)           wave1_out();
    method Bit#(1)           wave2_out();
endinterface
interface Uart;
    method Action            ctsn(Bit#(1) v);
    method Action            dcdn(Bit#(1) v);
    method Action            dsrn(Bit#(1) v);
    method Bit#(1)           dtrn();
    method Action            rin(Bit#(1) v);
    method Bit#(1)           rtsn();
    method Action            rx(Bit#(1) v);
    method Bit#(1)           tx();
endinterface
interface Usb;
    method Bit#(2)           port_indctl();
    method Action            vbus_pwrfault(Bit#(1) v);
    method Bit#(1)           vbus_pwrselect();
endinterface
interface I2c;
    interface Bidir(1)       scl;
    interface Bidir(1)       sda;
endinterface
interface Can;
    method Action            phy_rx(Bit#(1) v);
    method Bit#(1)           phy_tx();
endinterface
interface Core;
    method Action            n_fiq(Bit#(1) v);
    method Action            n_irq(Bit#(1) v);
endinterface

interface Ps7#(numeric type EMIO_GPIO_WIDTH);
    interface Can            can0;
    interface Can            can1;
    interface Core           core0;
    interface Core           core1;
    interface Ddr            ddr;
    interface Dma            dma0;
    interface Dma            dma1;
    interface Dma            dma2;
    interface Dma            dma3;
    interface Enet           enet0;
    interface Enet           enet1;
    method Action            event_eventi(Bit#(1) v);
    method Bit#(1)           event_evento();
    method Bit#(2)           event_standbywfe();
    method Bit#(2)           event_standbywfi();
    method Bit#(1)           fclk_clk0();
    method Bit#(1)           fclk_clk1();
    method Bit#(1)           fclk_clk2();
    method Bit#(1)           fclk_clk3();
    method Action            fclk_clktrig0_n(Bit#(1) v);
    method Action            fclk_clktrig1_n(Bit#(1) v);
    method Action            fclk_clktrig2_n(Bit#(1) v);
    method Action            fclk_clktrig3_n(Bit#(1) v);
    method Bit#(1)           fclk_reset0_n();
    method Bit#(1)           fclk_reset1_n();
    method Bit#(1)           fclk_reset2_n();
    method Bit#(1)           fclk_reset3_n();
    method Action            fpga_idle_n(Bit#(1) v);
    method Action            ftmd_tracein_atid(Bit#(4) v);
    method Action            ftmd_tracein_clk(Bit#(1) v);
    method Action            ftmd_tracein_data(Bit#(32) v);
    method Action            ftmd_tracein_valid(Bit#(1) v);
    method Action            ftmt_f2p_debug(Bit#(32) v);
    method Action            ftmt_f2p_trig(Bit#(4) v);
    method Bit#(4)           ftmt_f2p_trigack();
    method Bit#(32)          ftmt_p2f_debug();
    method Bit#(4)           ftmt_p2f_trig();
    method Action            ftmt_p2f_trigack(Bit#(4) v);
    interface Bidir(EMIO_GPIO_WIDTH) gpio;
    interface I2c            i2c0;
    interface I2c            i2c1;
    method Action            irq_f2p(Bit#(16) v);
    method Bit#(1)           irq_p2f_can0();
    method Bit#(1)           irq_p2f_can1();
    method Bit#(1)           irq_p2f_cti();
    method Bit#(1)           irq_p2f_dmac0();
    method Bit#(1)           irq_p2f_dmac1();
    method Bit#(1)           irq_p2f_dmac2();
    method Bit#(1)           irq_p2f_dmac3();
    method Bit#(1)           irq_p2f_dmac4();
    method Bit#(1)           irq_p2f_dmac5();
    method Bit#(1)           irq_p2f_dmac6();
    method Bit#(1)           irq_p2f_dmac7();
    method Bit#(1)           irq_p2f_dmac_abort();
    method Bit#(1)           irq_p2f_enet0();
    method Bit#(1)           irq_p2f_enet1();
    method Bit#(1)           irq_p2f_enet_wake0();
    method Bit#(1)           irq_p2f_enet_wake1();
    method Bit#(1)           irq_p2f_gpio();
    method Bit#(1)           irq_p2f_i2c0();
    method Bit#(1)           irq_p2f_i2c1();
    method Bit#(1)           irq_p2f_qspi();
    method Bit#(1)           irq_p2f_sdio0();
    method Bit#(1)           irq_p2f_sdio1();
    method Bit#(1)           irq_p2f_smc();
    method Bit#(1)           irq_p2f_spi0();
    method Bit#(1)           irq_p2f_spi1();
    method Bit#(1)           irq_p2f_uart0();
    method Bit#(1)           irq_p2f_uart1();
    method Bit#(1)           irq_p2f_usb0();
    method Bit#(1)           irq_p2f_usb1();
    method Bit#(MIO_PRIMITIVE)       mio();
    interface AxiSlaveCommon#(DATA_WIDTH, ID_WIDTH)    s_axi_acp;
    method Action            s_axi_acp_aruser(Bit#(5) v);
    method Action            s_axi_acp_awuser(Bit#(5) v);
    interface AxiSlaveCommon#(DATA_WIDTH, ID_WIDTH)    s_axi_gp0;
    interface AxiSlaveCommon#(DATA_WIDTH, ID_WIDTH)    s_axi_gp1;
    interface AxiSlaveHighSpeed#(DATA_WIDTH, ID_WIDTH) s_axi_hp0;
    interface AxiSlaveHighSpeed#(DATA_WIDTH, ID_WIDTH) s_axi_hp1;
    interface AxiSlaveHighSpeed#(DATA_WIDTH, ID_WIDTH) s_axi_hp2;
    interface AxiSlaveHighSpeed#(DATA_WIDTH, ID_WIDTH) s_axi_hp3;
    interface AxiMasterCommon#(DATA_WIDTH, ID_WIDTH)   m_axi_gp0;
    interface AxiMasterCommon#(DATA_WIDTH, ID_WIDTH)   m_axi_gp1;
    method Action            pjtag_tck(Bit#(1) v);
    interface Bidir(1)       pjtag_td;
    method Action            pjtag_tms(Bit#(1) v);
    method Action            ps_clk(Bit#(1) v);
    method Action            ps_porb(Bit#(1) v);
    method Action            ps_srstb(Bit#(1) v);
    interface Sdio           sdio0;
    interface Sdio           sdio1;
    interface Spi            spi0;
    interface Spi            spi1;
    method Action            sram_intin(Bit#(1) v);
    method Action            trace_clk(Bit#(1) v);
    method Bit#(1)           trace_ctl();
    method Bit#(32)          trace_data();
    interface Ttc            ttc0;
    interface Ttc            ttc1;
    interface Uart           uart0;
    interface Uart           uart1;
    interface Usb            usb0;
    interface Usb            usb1;
    method Action            wdt_clk_in(Bit#(1) v);
    method Bit#(1)           wdt_rst_out();

   schedule (datain, idatain, inc, ce) CF (datain, idatain, inc, ce);
endmodule

// 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 Clocks       :: *;
import DefaultValue :: *;
import XilinxCells  :: *;
import Vector       :: *;

(* always_ready, always_enabled *)
interface AxiREQ#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    Bit#(32)             ADDR;
    Bit#(2)              BURST;
    Bit#(4)              CACHE;
    Bit#(C_ID_WIDTH)     ID;
    Bit#(4)              LEN;
    Bit#(2)              LOCK;
    Bit#(3)              PROT;
    Bit#(4)              QOS;
    Bit#(3)              SIZE;
    Bit#(1)              VALID;
endinterface
interface AxiMOSI#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    AxiREQ               AR;
    AxiREQ               AW;
    Bit#(1)              BREADY;
    Bit#(1)              RREADY;
    Bit#(C_DATA_WIDTH)   WDATA;
    Bit#(C_ID_WIDTH)     WID;
    Bit#(1)              WLAST;
    Bit#(C_DATA_WIDTH/8) WSTRB;
    Bit#(1)              WVALID;
endinterface
interface AxiVALID#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    Bit#(C_ID_WIDTH)     ID;
    Bit#(2)              RESP;
    Bit#(1)              VALID;
endinterface
interface AxiMISO(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    Bit#(1)              ARREADY;
    Bit#(1)              AWREADY;
    AxiVALID#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH) B;
    AxiVALID#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH) R;
    Bit#(C_DATA_WIDTH)   RDATA;
    Bit#(1)              RLAST;
    Bit#(1)              WREADY;
endinterface
interface AxiMasterCommon#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    method Action ACLK(Bit#(1) v); // common
    method Bit#(1) ARESETN();      // common
    AxiMOSI#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    AxiMISO#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    method Action ARADDR(Bit#(32) v);
    method Bit#(1) ARREADY();
endinterface

interface AxiMasterHighSpeed#(numeric type C_DATA_WIDTH, numeric type C_ID_WIDTH);
    interface AxiCommon#(C_DATA_WIDTH, C_ID_WIDTH) axi;
    method Bit#(3) RACOUNT();
    method Bit#(8) RCOUNT();
    method Action RDISSUECAP1_EN(Bit#(1) v);
    method Bit#(6) WACOUNT();
    method Bit#(8) WCOUNT();
    method Action WRISSUECAP1_EN(Bit#(1) v);
endinterface
interface Ddr;
    method Bit#(15) DDR_Addr();
    method Bit#(3) DDR_BankAddr();
    method Bit#(1) DDR_CAS_n();
    method Bit#(1) DDR_CKE();
    method Bit#(1) DDR_CS_n();
    method Bit#(1) DDR_Clk();
    method Bit#(1) DDR_Clk_n();
    method Bit#(C_DM_WIDTH) DDR_DM();
    method Bit#(C_DQ_WIDTH) DDR_DQ();
    method Bit#(C_DQS_WIDTH) DDR_DQS();
    method Bit#(C_DQS_WIDTH) DDR_DQS_n();
    method Bit#(1) DDR_DRSTB();
    method Bit#(1) DDR_ODT();
    method Bit#(1) DDR_RAS_n();
    method Bit#(1) DDR_VRN();
    method Bit#(1) DDR_VRP();
    method Bit#(1) DDR_WEB();
endinterface
interface Dma;
    method Action DMA0_ACLK(Bit#(1) v);
    method Action DMA0_DAREADY(Bit#(1) v);
    method Bit#(2) DMA0_DATYPE();
    method Bit#(1) DMA0_DAVALID();
    method Action DMA0_DRLAST(Bit#(1) v);
    method Bit#(1) DMA0_DRREADY();
    method Action DMA0_DRTYPE(Bit#(2) v);
    method Action DMA0_DRVALID(Bit#(1) v);
    method Bit#(1) DMA0_RSTN();
endinterface
interface Enet;
    method Action ENET0_EXT_INTIN(Bit#(1) v);
    method Action ENET0_GMII_COL(Bit#(1) v);
    method Action ENET0_GMII_CRS(Bit#(1) v);
    method Action ENET0_GMII_RXD(Bit#(8) v);
    method Action ENET0_GMII_RX_CLK(Bit#(1) v);
    method Action ENET0_GMII_RX_DV(Bit#(1) v);
    method Action ENET0_GMII_RX_ER(Bit#(1) v);
    method Bit#(8) ENET0_GMII_TXD();
    method Action ENET0_GMII_TX_CLK(Bit#(1) v);
    method Bit#(1) ENET0_GMII_TX_EN();
    method Bit#(1) ENET0_GMII_TX_ER();
    method Action ENET0_MDIO_I(Bit#(1) v);
    method Bit#(1) ENET0_MDIO_MDC();
    method Bit#(1) ENET0_MDIO_O();
    method Bit#(1) ENET0_MDIO_T();
    method Bit#(1) ENET0_PTP_DELAY_REQ_RX();
    method Bit#(1) ENET0_PTP_DELAY_REQ_TX();
    method Bit#(1) ENET0_PTP_PDELAY_REQ_RX();
    method Bit#(1) ENET0_PTP_PDELAY_REQ_TX();
    method Bit#(1) ENET0_PTP_PDELAY_RESP_RX();
    method Bit#(1) ENET0_PTP_PDELAY_RESP_TX();
    method Bit#(1) ENET0_PTP_SYNC_FRAME_RX();
    method Bit#(1) ENET0_PTP_SYNC_FRAME_TX();
    method Bit#(1) ENET0_SOF_RX();
    method Bit#(1) ENET0_SOF_TX();
endinterface
interface Sdio;
    method Bit#(1) SDIO0_BUSPOW();
    method Bit#(3) SDIO0_BUSVOLT();
    method Action SDIO0_CDN(Bit#(1) v);
    method Bit#(1) SDIO0_CLK();
    method Action SDIO0_CLK_FB(Bit#(1) v);
    method Action SDIO0_CMD_I(Bit#(1) v);
    method Bit#(1) SDIO0_CMD_O();
    method Bit#(1) SDIO0_CMD_T();
    method Action SDIO0_DATA_I(Bit#(4) v);
    method Bit#(4) SDIO0_DATA_O();
    method Bit#(4) SDIO0_DATA_T();
    method Bit#(1) SDIO0_LED();
    method Action SDIO0_WP(Bit#(1) v);
endinterface
interface Spi;
    method Action SPI0_MISO_I(Bit#(1) v);
    method Bit#(1) SPI0_MISO_O();
    method Bit#(1) SPI0_MISO_T();
    method Action SPI0_MOSI_I(Bit#(1) v);
    method Bit#(1) SPI0_MOSI_O();
    method Bit#(1) SPI0_MOSI_T();
    method Action SPI0_SCLK_I(Bit#(1) v);
    method Bit#(1) SPI0_SCLK_O();
    method Bit#(1) SPI0_SCLK_T();
    method Bit#(1) SPI0_SS1_O();
    method Bit#(1) SPI0_SS2_O();
    method Action SPI0_SS_I(Bit#(1) v);
    method Bit#(1) SPI0_SS_O();
    method Bit#(1) SPI0_SS_T();
endinterface
interface Ttc;
    method Action TTC0_CLK0_IN(Bit#(1) v);
    method Action TTC0_CLK1_IN(Bit#(1) v);
    method Action TTC0_CLK2_IN(Bit#(1) v);
    method Bit#(1) TTC0_WAVE0_OUT();
    method Bit#(1) TTC0_WAVE1_OUT();
    method Bit#(1) TTC0_WAVE2_OUT();
endinterface
interface Uart;
    method Action UART0_CTSN(Bit#(1) v);
    method Action UART0_DCDN(Bit#(1) v);
    method Action UART0_DSRN(Bit#(1) v);
    method Bit#(1) UART0_DTRN();
    method Action UART0_RIN(Bit#(1) v);
    method Bit#(1) UART0_RTSN();
    method Action UART0_RX(Bit#(1) v);
    method Bit#(1) UART0_TX();
endinterface
interface Usb;
    method Bit#(2) USB0_PORT_INDCTL();
    method Action USB0_VBUS_PWRFAULT(Bit#(1) v);
    method Bit#(1) USB0_VBUS_PWRSELECT();
endinterface
interface I2c;
    method Action I2C0_SCL_I(Bit#(1) v);
    method Bit#(1) I2C0_SCL_O();
    method Bit#(1) I2C0_SCL_T();
    method Action I2C0_SDA_I(Bit#(1) v);
    method Bit#(1) I2C0_SDA_O();
    method Bit#(1) I2C0_SDA_T();
endinterface

interface Ps7#(numeric type C_EMIO_GPIO_WIDTH);
    method Action CAN0_PHY_RX(Bit#(1) v);
    method Bit#(1) CAN0_PHY_TX();
    method Action CAN1_PHY_RX(Bit#(1) v);
    method Bit#(1) CAN1_PHY_TX();
    method Action Core0_nFIQ(Bit#(1) v);
    method Action Core0_nIRQ(Bit#(1) v);
    method Action Core1_nFIQ(Bit#(1) v);
    method Action Core1_nIRQ(Bit#(1) v);
    method Action DDR_ARB(Bit#(4) v);
    interface Ddr DDR;
    interface Dma DMA0;
    interface Dma DMA1;
    interface Dma DMA2;
    interface Dma DMA3;
    interface Enet ENET0;
    interface Enet ENET1;
    method Action EVENT_EVENTI(Bit#(1) v);
    method Bit#(1) EVENT_EVENTO();
    method Bit#(2) EVENT_STANDBYWFE();
    method Bit#(2) EVENT_STANDBYWFI();
    method Bit#(1) FCLK_CLK0();
    method Bit#(1) FCLK_CLK1();
    method Bit#(1) FCLK_CLK2();
    method Bit#(1) FCLK_CLK3();
    method Action FCLK_CLKTRIG0_N(Bit#(1) v);
    method Action FCLK_CLKTRIG1_N(Bit#(1) v);
    method Action FCLK_CLKTRIG2_N(Bit#(1) v);
    method Action FCLK_CLKTRIG3_N(Bit#(1) v);
    method Bit#(1) FCLK_RESET0_N();
    method Bit#(1) FCLK_RESET1_N();
    method Bit#(1) FCLK_RESET2_N();
    method Bit#(1) FCLK_RESET3_N();
    method Action FPGA_IDLE_N(Bit#(1) v);
    method Action FTMD_TRACEIN_ATID(Bit#(4) v);
    method Action FTMD_TRACEIN_CLK(Bit#(1) v);
    method Action FTMD_TRACEIN_DATA(Bit#(32) v);
    method Action FTMD_TRACEIN_VALID(Bit#(1) v);
    method Action FTMT_F2P_DEBUG(Bit#(32) v);
    method Action FTMT_F2P_TRIG(Bit#(4) v);
    method Bit#(4) FTMT_F2P_TRIGACK();
    method Bit#(32) FTMT_P2F_DEBUG();
    method Bit#(4) FTMT_P2F_TRIG();
    method Action FTMT_P2F_TRIGACK(Bit#(4) v);
    method Action GPIO_I(Bit#(C_EMIO_GPIO_WIDTH) v);
    method Bit#(C_EMIO_GPIO_WIDTH) GPIO_O();
    method Bit#(C_EMIO_GPIO_WIDTH) GPIO_T();
    interface I2c I2C0;
    interface I2c I2C1;
    method Action IRQ_F2P(Bit#(16) v);
    method Bit#(1) IRQ_P2F_CAN0();
    method Bit#(1) IRQ_P2F_CAN1();
    method Bit#(1) IRQ_P2F_CTI();
    method Bit#(1) IRQ_P2F_DMAC0();
    method Bit#(1) IRQ_P2F_DMAC1();
    method Bit#(1) IRQ_P2F_DMAC2();
    method Bit#(1) IRQ_P2F_DMAC3();
    method Bit#(1) IRQ_P2F_DMAC4();
    method Bit#(1) IRQ_P2F_DMAC5();
    method Bit#(1) IRQ_P2F_DMAC6();
    method Bit#(1) IRQ_P2F_DMAC7();
    method Bit#(1) IRQ_P2F_DMAC_ABORT();
    method Bit#(1) IRQ_P2F_ENET0();
    method Bit#(1) IRQ_P2F_ENET1();
    method Bit#(1) IRQ_P2F_ENET_WAKE0();
    method Bit#(1) IRQ_P2F_ENET_WAKE1();
    method Bit#(1) IRQ_P2F_GPIO();
    method Bit#(1) IRQ_P2F_I2C0();
    method Bit#(1) IRQ_P2F_I2C1();
    method Bit#(1) IRQ_P2F_QSPI();
    method Bit#(1) IRQ_P2F_SDIO0();
    method Bit#(1) IRQ_P2F_SDIO1();
    method Bit#(1) IRQ_P2F_SMC();
    method Bit#(1) IRQ_P2F_SPI0();
    method Bit#(1) IRQ_P2F_SPI1();
    method Bit#(1) IRQ_P2F_UART0();
    method Bit#(1) IRQ_P2F_UART1();
    method Bit#(1) IRQ_P2F_USB0();
    method Bit#(1) IRQ_P2F_USB1();
    method Bit#(C_MIO_PRIMITIVE) MIO();
    interface AxiSlaveCommon#(1) s_axi_acp;
>     method Action ARUSER(Bit#(5) v);
>     method Action AWUSER(Bit#(5) v);
    interface AxiSlaveCommon#(1) s_axi_gp0;
    interface AxiSlaveCommon#(1) s_axi_gp1;
    interface AxiSlaveHighSpeed#(1) s_axi_hp0;
    interface AxiSlaveHighSpeed#(1) s_axi_hp1;
    interface AxiSlaveHighSpeed#(1) s_axi_hp2;
    interface AxiSlaveHighSpeed#(1) s_axi_hp3;
    interface AxiMasterCommon#(1) m_axi_gp0;
    interface AxiMasterCommon#(1) m_axi_gp1;
    method Action PJTAG_TCK(Bit#(1) v);
    method Action PJTAG_TD_I(Bit#(1) v);
    method Bit#(1) PJTAG_TD_O();
    method Bit#(1) PJTAG_TD_T();
    method Action PJTAG_TMS(Bit#(1) v);
    method Action PS_CLK(Bit#(1) v);
    method Action PS_PORB(Bit#(1) v);
    method Action PS_SRSTB(Bit#(1) v);
    interface Sdio SDIO0;
    interface Sdio SDIO1;
    interface Spi SPI0;
    interface Spi SPI1;
    method Action SRAM_INTIN(Bit#(1) v);
    method Action TRACE_CLK(Bit#(1) v);
    method Bit#(1) TRACE_CTL();
    method Bit#(32) TRACE_DATA();
    interface Ttc TTC0;
    interface Ttc TTC1;
    interface Uart UART0;
    interface Uart UART1;
    interface Usb USB0;
    interface Usb USB1;
    method Action WDT_CLK_IN(Bit#(1) v);
    method Bit#(1) WDT_RST_OUT();

   schedule (datain, idatain, inc, ce) CF (datain, idatain, inc, ce);
endmodule