dakies/OSS_Verilog huggingface dataset:
module wfid_mux_8to1 (
  wr_port_select,

  wfid_done_0,
  wfid_0,
  wfid_done_1,
  wfid_1,
  wfid_done_2,
  wfid_2,
  wfid_done_3,
  wfid_3,
  wfid_done_4,
  wfid_4,
  wfid_done_5,
  wfid_5,
  wfid_done_6,
  wfid_6,
  wfid_done_7,
  wfid_7,
  muxed_wfid,
  muxed_wfid_done
);

  output [5:0] muxed_wfid;
  output muxed_wfid_done;

  input [15:0] wr_port_select;

  input wfid_done_0;
  input [5:0] wfid_0;
  input wfid_done_1;
  input [5:0] wfid_1;
  input wfid_done_2;
  input [5:0] wfid_2;
  input wfid_done_3;
  input [5:0] wfid_3;
  input wfid_done_4;
  input [5:0] wfid_4;
  input wfid_done_5;
  input [5:0] wfid_5;
  input wfid_done_6;
  input [5:0] wfid_6;
  input wfid_done_7;
  input [5:0] wfid_7;

  reg [5:0] muxed_wfid;
  reg muxed_wfid_done;

  always @ (
    wr_port_select or
    wfid_done_0 or
    wfid_0 or
    wfid_done_1 or
    wfid_1 or
    wfid_done_2 or
    wfid_2 or
    wfid_done_3 or
    wfid_3 or
    wfid_done_4 or
    wfid_4 or
    wfid_done_5 or
    wfid_5 or
    wfid_done_6 or
    wfid_6 or
    wfid_done_7 or
    wfid_7
  ) begin
    casex(wr_port_select)
      16'h0001:
        begin
          muxed_wfid_done <= wfid_done_0;
          muxed_wfid <= wfid_0;
        end
      16'h0002:
        begin
          muxed_wfid_done <= wfid_done_1;
          muxed_wfid <= wfid_1;
        end
      16'h0004:
        begin
          muxed_wfid_done <= wfid_done_2;
          muxed_wfid <= wfid_2;
        end
      16'h0008:
        begin
          muxed_wfid_done <= wfid_done_3;
          muxed_wfid <= wfid_3;
        end
      16'h0010:
        begin
          muxed_wfid_done <= wfid_done_4;
          muxed_wfid <= wfid_4;
        end
      16'h0020:
        begin
          muxed_wfid_done <= wfid_done_5;
          muxed_wfid <= wfid_5;
        end
      16'h0040:
        begin
          muxed_wfid_done <= wfid_done_6;
          muxed_wfid <= wfid_6;
        end
      16'h0080:
        begin
          muxed_wfid_done <= wfid_done_7;
          muxed_wfid <= wfid_7;
        end
      16'h0100:
        begin
          muxed_wfid_done <= 1'b0;
          muxed_wfid <= {6{1'bx}};
        end
      16'h0000:
        begin
          muxed_wfid_done <= 1'b0;
          muxed_wfid <= {6{1'bx}};
        end
      default:
        begin
          muxed_wfid_done <= 1'bx;
          muxed_wfid <= {6{1'bx}};
        end
    endcase
  end

endmodule
module vgpr_2to1_rd_port_mux (
  port0_rd_en,
  port0_rd_addr,

  port1_rd_en,
  port1_rd_addr,

  port_rd_data,

  rd_addr,
  rd_data
);
// S: changed to 2k (parameter passed)
  parameter DATAWIDTH = 2048;

  input         port0_rd_en;
  input [9:0]   port0_rd_addr;

  input         port1_rd_en;
  input [9:0]   port1_rd_addr;

  input [DATAWIDTH-1:0] rd_data;
  output [DATAWIDTH-1:0] port_rd_data;
  output [9:0]  rd_addr;

  reg [9:0]     rd_addr;

  assign port_rd_data = rd_data;

  always @ (
    port0_rd_en or
    port1_rd_en or
    port0_rd_addr or
    port1_rd_addr
  ) begin
      casex({port1_rd_en,port0_rd_en})
        2'b01:
          begin
            rd_addr <= port0_rd_addr;
          end
        2'b10:
          begin
            rd_addr <= port1_rd_addr;
          end
        default:
          begin
            rd_addr <= {10{1'bx}};
          end
      endcase
    end

endmodule
module reg_1024x32b_3r_1w (/*AUTOARG*/
			   // Outputs
			   rd0_data, rd1_data, rd2_data,
			   // Inputs
			   rd0_addr, rd1_addr, rd2_addr, wr0_addr, wr0_en, wr0_data, clk
			   );

   //innitial test will only include all 32b ops
   //keep 128 bit bus for future
   output [31:0]  rd0_data;
   output [31:0]  rd1_data;
   output [31:0]  rd2_data;

   //10 bit addr -> 1024 locations
   input [9:0] 	  rd0_addr;
   input [9:0] 	  rd1_addr;
   input [9:0] 	  rd2_addr;

   input [9:0] 	  wr0_addr;
   input [3:0] 	  wr0_en; //extern 4 bit enable [legacy--4 bits determined vector length]
   input [31:0]   wr0_data;

   input 	  clk;

   reg [31:0] 		      rd0_data;
   reg [31:0] 		      rd1_data;
   reg [31:0] 		      rd2_data;
   wire [31:0] 		      rd0_data_bank0;

   wire [9:0] 	  rd0_addr_last;
   wire [9:0] 	  rd1_addr_last;
   wire [9:0] 	  rd2_addr_last;

   dff rd_addr_data_path_delay[10+10+10-1:0]
     (.q({rd0_addr_last, rd1_addr_last, rd2_addr_last}),
      .d({rd0_addr, rd1_addr, rd2_addr}),
      .clk(clk),
      .rst(1'b0));

   // Rd data path
   always @(rd0_addr_last or rd0_data_bank0)//or rd0_data_bank1 or rd0_data_bank2 or rd0_data_bank3)
     begin
	//rd0_data <= {{96{1'b0}},rd0_data_bank0};
	// S: change to 32b line
	rd0_data <= rd0_data_bank0;
     end

   wire [31:0] rd1_data_bank0;
   always @(rd1_addr_last or rd1_data_bank0)// or rd1_data_bank1 or rd1_data_bank2 or rd1_data_bank3)
     begin
	rd1_data <= rd1_data_bank0;
     end

   wire [31:0] rd2_data_bank0;

   always @(rd2_addr_last or rd2_data_bank0)// or rd2_data_bank1 or rd2_data_bank2 or rd2_data_bank3)
     begin

	rd2_data <= rd2_data_bank0;

     end
`ifdef FPGA_BUILD
  reg_256x32b_3r_1w_fpga
`else
  reg_256x32b_3r_1w
`endif
   bank0(
    .rd0_addr(rd0_addr),
    .rd0_data(rd0_data_bank0),
    .rd1_addr(rd1_addr),
    .rd1_data(rd1_data_bank0),
    .rd2_addr(rd2_addr),
    .rd2_data(rd2_data_bank0),
    .wr0_addr(wr0_addr), //connect write address straight in
    .wr0_en(wr0_en[0]|wr0_en[1]|wr0_en[2]|wr0_en[3]),  //only focus on 32b, so only enable if bottom bit active high
    .wr0_data(wr0_data[31:0]),
    .clk(clk)
  );

endmodule
module reg_8x64b_1r_1w (
  rd_addr,
  rd_data,

  wr_en,
  wr_addr,
  wr_data,

  clk,
  rst
);

  output [63:0] rd_data;
  input [2:0] rd_addr;

  input [2:0] wr_addr;
  input wr_en;
  input [63:0] wr_data;

  input clk;
  input rst;

  wire [511:0] word_out;
  wire [7:0] wr_word_select;
  wire [7:0] wr_en_word;

  mux_8x64b_to_1x64b mux_rd_port (.out(rd_data), .in(word_out), .select(rd_addr));
  decoder_3_to_8 decoder_wr_port (.out(wr_word_select), .in(wr_addr));
  assign wr_en_word = {8{wr_en}} & wr_word_select;

  reg_64b word[7:0] (.out(word_out), .in(wr_data), .wr_en(wr_en_word), .clk(clk), .rst(rst));

endmodule
module PS_flops_fetch_wavepool (
 buff_tag,
 buff_instr,
 buff_ack,
 flopped_buff_wfid,
 flopped_buff_instr_pc,
 flopped_buff_first,
 flopped_buff_ack,
 clk,
 rst
);

input [38:0] buff_tag;
input [31:0] buff_instr;
input buff_ack;
output [5:0] flopped_buff_wfid;
output [63:0] flopped_buff_instr_pc;
output flopped_buff_first;
output flopped_buff_ack;
input clk;
input rst;

dff flop_wfid[5:0] (.q(flopped_buff_wfid), .d(buff_tag[37:32]), .clk(clk), .rst(rst));
dff flop_instr_pc[63:0] (.q(flopped_buff_instr_pc), .d({buff_instr,buff_tag[31:0]}), .clk(clk), .rst(rst));
dff flop_first (.q(flopped_buff_first), .d(buff_tag[38]), .clk(clk), .rst(rst));
dff flop_ack (.q(flopped_buff_ack), .d(buff_ack), .clk(clk), .rst(rst));

endmodule
module adder3bit (
	sum,
	cout,
	in1,
	in2
);

output[2:0] sum;
output cout;

input[2:0] in1, in2;

wire cout0, cout1;

adder1bit add0(sum[0], cout0, in1[0], in2[0], 1'b0);
adder1bit add1(sum[1], cout1, in1[1], in2[1], cout0);
adder1bit add2(sum[2], cout, in1[2], in2[2], cout1);

endmodule
module queue_controller (
  q_vtail_incr,
  q_rd,
  q_wr,
  q_reset,
  q_empty,
  stop_fetch,
  buff_rd_addr,
  buff_wr_addr,
  buff_wr_en,
  clk,
  rst
);

input q_vtail_incr;
input q_rd;
input q_wr;
input q_reset;

output q_empty;
output stop_fetch;
output [2:0] buff_rd_addr;
output [2:0] buff_wr_addr;
output buff_wr_en;
input clk;
input rst;

wire [2:0] vtail;
wire [2:0] tail;
wire [2:0] head;

wire [2:0] next_vtail;
wire [2:0] next_tail;
wire [2:0] next_head;
wire [2:0] next_vtail_qualified;
wire [2:0] next_tail_qualified;
wire [2:0] next_head_qualified;

wire [2:0] vtail_plus2;

assign next_vtail_qualified = next_vtail & ~{3{q_reset}};
assign next_tail_qualified = next_tail & ~{3{q_reset}};
assign next_head_qualified = next_head & ~{3{q_reset}};

reg_3b Vtail(.out(vtail), .in(next_vtail_qualified), .wr_en(q_vtail_incr|q_reset), .clk(clk), .rst(rst));
reg_3b Tail(.out(tail), .in(next_tail_qualified), .wr_en(q_wr|q_reset), .clk(clk), .rst(rst));
reg_3b Head(.out(head), .in(next_head_qualified), .wr_en(q_rd|q_reset), .clk(clk), .rst(rst));

adder3bit Vtail_Incr(.sum(next_vtail), .cout(), .in1(vtail), .in2(3'b1));
adder3bit Tail_Incr(.sum(next_tail), .cout(), .in1(tail), .in2(3'b1));
adder3bit Head_Incr(.sum(next_head), .cout(), .in1(head), .in2(3'b1));

adder3bit Vtail_Plus2(.sum(vtail_plus2), .cout(), .in1(vtail), .in2(3'd2));

assign q_empty = (head == tail);
assign stop_fetch = (head == next_vtail) | (head == vtail_plus2);

assign buff_rd_addr = head;
assign buff_wr_addr = tail;
assign buff_wr_en = q_wr;

endmodule
module reg_3b (out, in, wr_en, clk, rst);

  output [2:0] out;
  input [2:0] in;
  input wr_en;
  input clk;
  input rst;

  dff_en bits[2:0] (.q(out), .d(in), .en(wr_en), .clk(clk), .rst(rst));

endmodule
module wave_queue (
  q_vtail_incr,
  q_rd,
  q_wr,
  q_reset,
  q_empty,
  stop_fetch,
  instr_pc_in,
  instr_pc_out,
  clk,
  rst
);

input q_vtail_incr;
input q_rd;
input q_wr;
input q_reset;

output q_empty;
output stop_fetch;

input [63:0] instr_pc_in;
output [63:0] instr_pc_out;

input clk;
input rst;

wire [2:0] buff_rd_addr;
wire [2:0] buff_wr_addr;
wire  buff_wr_en;

queue_controller q_cntrl (
  .q_vtail_incr(q_vtail_incr),
  .q_rd(q_rd),
  .q_wr(q_wr),
  .q_reset(q_reset),
  .q_empty(q_empty),
  .stop_fetch(stop_fetch),
  .buff_rd_addr(buff_rd_addr),
  .buff_wr_addr(buff_wr_addr),
  .buff_wr_en(buff_wr_en),
  .clk(clk),
  .rst(rst)
);

reg_8x64b_1r_1w q_buff(
  .rd_addr(buff_rd_addr),
  .rd_data(instr_pc_out),
  .wr_en(buff_wr_en),
  .wr_addr(buff_wr_addr),
  .wr_data(instr_pc_in),
  .clk(clk),
  .rst(rst)
);

endmodule
module reg_40x35b_1r_1w (
  rd_addr,
  rd_data,

  wr_en,
  wr_addr,
  wr_data,

  clk,
  rst
);

  output [34:0] rd_data;
  input [5:0] rd_addr;

  input [5:0] wr_addr;
  input wr_en;
  input [34:0] wr_data;

  input clk;
  input rst;

  wire [1399:0] word_out;
  wire [39:0] wr_word_select;
  wire [39:0] wr_en_word;

  mux_40x35b_to_1x35b mux_rd_port (.out(rd_data), .in(word_out), .select(rd_addr));
  decoder_6_to_40 decoder_wr_port (.out(wr_word_select), .in(wr_addr));
  assign wr_en_word = {40{wr_en}} & wr_word_select;

  reg_35b word[39:0](.out(word_out), .in(wr_data), .wr_en(wr_en_word), .clk(clk), .rst(rst));

endmodule
module reg_35b (out, in, wr_en, clk, rst);

  output [34:0] out;
  input [34:0] in;
  input wr_en;
  input clk;
  input rst;

  dff_en bits[34:0] (.q(out), .d(in), .en(wr_en), .clk(clk), .rst(rst));

endmodule
module scbd_feeder(
  valid_wf,
  ins_half_reqd,
  ins_half_wfid,
  issue_vacant,
  q_empty,
  q_reset,
  feed_valid,
  feed_wfid,
  clk,
  rst
);

input [39:0] valid_wf;

input ins_half_reqd;
input [5:0] ins_half_wfid;
input [39:0] issue_vacant;
input [39:0] q_empty;
input [39:0] q_reset;

output feed_valid;
output [5:0] feed_wfid;


input clk;
input rst;

wire [39:0] ins_half_reqd_bitwise;
wire [39:0] selected_instr_bitwise;
wire [39:0] hungry;
wire [39:0] next_hungry;
wire [39:0] sb_candidates;

decoder_6_to_40 ins_half_dec(.out(ins_half_reqd_bitwise), .in(ins_half_wfid));

assign next_hungry = (issue_vacant | (ins_half_reqd_bitwise & {40{ins_half_reqd}}) | q_reset | hungry) & (~ ({40{feed_valid}} & selected_instr_bitwise));

reg_40b_set scbd_hungry(.out(hungry), .in(next_hungry), .wr_en(1'b1), .clk(clk), .set(rst));

assign sb_candidates = hungry & (~ q_empty) & valid_wf;

priority_encoder_40to6 select_enc(.binary_out(feed_wfid), .valid(feed_valid), .encoder_in(sb_candidates), .enable(1'b1));

decoder_6_to_40 update_dec(.out(selected_instr_bitwise), .in(feed_wfid));

endmodule
module wavepool_controller (
  buff_wfid,
  buff_first,
  buff_ack,
  q_wr,
  reserve_slotid,
  reserve_valid,
  q_vtail_incr,
  halt_wfid,
  wf_halt,
  branch_wfid,
  branch_en,
  branch_taken,
  q_reset,
  feed_wfid,
  feed_valid,
  q_rd,
  valid_wf,
  decode_wfid,
  decode_instr_valid,
  clk,
  rst
);

input [5:0] buff_wfid;
input buff_first;
input buff_ack;
output [39:0] q_wr;

input [5:0] reserve_slotid;
input reserve_valid;
output [39:0] q_vtail_incr;

input [5:0] halt_wfid;
input wf_halt;
input [5:0] branch_wfid;
input branch_en;
input branch_taken;
output [39:0] q_reset;

input [5:0] feed_wfid;
input feed_valid;
output [39:0] q_rd;

output [39:0] valid_wf;

output [5:0] decode_wfid;
output decode_instr_valid;

input clk;
input rst;

wire [39:0] next_valid_wf;
wire [39:0] valid_wf;
wire [39:0] temp_q_wr;
wire [39:0] temp_q_vtail_incr;
wire [39:0] halt_temp_q_reset;
wire [39:0] branch_temp_q_reset;
wire [39:0] temp_q_rd;
wire branch_taken_en;

reg_40b valid_wavefront(.out(valid_wf), .in(next_valid_wf), .wr_en(1'b1), .clk(clk), .rst(rst));
assign next_valid_wf = (valid_wf | ((temp_q_wr & {40{buff_ack}}) & {40{buff_first}})) & (~q_reset);

decoder_6_to_40 dec_q_wr(.out(temp_q_wr), .in(buff_wfid));
assign q_wr = (temp_q_wr & {40{buff_ack}}) & ({40{buff_first}} | valid_wf);

decoder_6_to_40 dec_q_vtail_incr(.out(temp_q_vtail_incr), .in(reserve_slotid));
assign q_vtail_incr = temp_q_vtail_incr & {40{reserve_valid}};

decoder_6_to_40 dec_q_reset_halt(.out(halt_temp_q_reset), .in(halt_wfid));
decoder_6_to_40 dec_q_reset_branch(.out(branch_temp_q_reset), .in(branch_wfid));
assign branch_taken_en = branch_taken & branch_en;
assign q_reset = (halt_temp_q_reset & {40{wf_halt}}) | (branch_temp_q_reset & {40{branch_taken_en}});

decoder_6_to_40 dec_q_rd(.out(temp_q_rd), .in(feed_wfid));
assign q_rd = temp_q_rd & {40{feed_valid}};

assign decode_wfid = feed_wfid;
assign decode_instr_valid = feed_valid;

endmodule
module wq_pool (
  q_vtail_incr,
  q_rd,
  q_wr,
  q_reset,
  q_empty,
  stop_fetch,
  instr_pc_in,
  instr_pc_out,
  wf_select,
  clk,
  rst
);

input [39:0] q_vtail_incr;
input [39:0] q_rd;
input [39:0] q_wr;
input [39:0] q_reset;

output [39:0] q_empty;
output [39:0] stop_fetch;

input [63:0] instr_pc_in;
output [63:0] instr_pc_out;

input [5:0] wf_select;
input clk;
input rst;

wire [2559:0] instr_pc_premux;

  wave_queue wf_queue[39:0] (
    .q_vtail_incr(q_vtail_incr),
    .q_rd(q_rd),
    .q_wr(q_wr),
    .q_reset(q_reset),
    .q_empty(q_empty),
    .stop_fetch(stop_fetch),
    .instr_pc_in(instr_pc_in),
    .instr_pc_out(instr_pc_premux),
    .clk(clk),
    .rst(rst)
  );

  mux_40x64b_to_1x64b mux_rd_port (.out(instr_pc_out), .in(instr_pc_premux), .select(wf_select));

endmodule
module mux_40xPARAMb_to_1xPARAMb(
            out,
            in,
            select );

    parameter WORD_WIDTH = 12; 

    input[40*WORD_WIDTH-1:0] in;
    input[5:0] select;
    output[WORD_WIDTH-1:0] out;
    
    reg[WORD_WIDTH-1:0] out;
    always @(in or select) begin
        casex(select)
            6'h00: out = in[1*WORD_WIDTH-1:0*WORD_WIDTH];
            6'h01: out = in[2*WORD_WIDTH-1:1*WORD_WIDTH];
            6'h02: out = in[3*WORD_WIDTH-1:2*WORD_WIDTH];
            6'h03: out = in[4*WORD_WIDTH-1:3*WORD_WIDTH];
            6'h04: out = in[5*WORD_WIDTH-1:4*WORD_WIDTH];
            6'h05: out = in[6*WORD_WIDTH-1:5*WORD_WIDTH];
            6'h06: out = in[7*WORD_WIDTH-1:6*WORD_WIDTH];
            6'h07: out = in[8*WORD_WIDTH-1:7*WORD_WIDTH];
            6'h08: out = in[9*WORD_WIDTH-1:8*WORD_WIDTH];
            6'h09: out = in[10*WORD_WIDTH-1:9*WORD_WIDTH];
            6'h0a: out = in[11*WORD_WIDTH-1:10*WORD_WIDTH];
            6'h0b: out = in[12*WORD_WIDTH-1:11*WORD_WIDTH];
            6'h0c: out = in[13*WORD_WIDTH-1:12*WORD_WIDTH];
            6'h0d: out = in[14*WORD_WIDTH-1:13*WORD_WIDTH];
            6'h0e: out = in[15*WORD_WIDTH-1:14*WORD_WIDTH];
            6'h0f: out = in[16*WORD_WIDTH-1:15*WORD_WIDTH];
            6'h10: out = in[17*WORD_WIDTH-1:16*WORD_WIDTH];
            6'h11: out = in[18*WORD_WIDTH-1:17*WORD_WIDTH];
            6'h12: out = in[19*WORD_WIDTH-1:18*WORD_WIDTH];
            6'h13: out = in[20*WORD_WIDTH-1:19*WORD_WIDTH];
            6'h14: out = in[21*WORD_WIDTH-1:20*WORD_WIDTH];
            6'h15: out = in[22*WORD_WIDTH-1:21*WORD_WIDTH];
            6'h16: out = in[23*WORD_WIDTH-1:22*WORD_WIDTH];
            6'h17: out = in[24*WORD_WIDTH-1:23*WORD_WIDTH];
            6'h18: out = in[25*WORD_WIDTH-1:24*WORD_WIDTH];
            6'h19: out = in[26*WORD_WIDTH-1:25*WORD_WIDTH];
            6'h1a: out = in[27*WORD_WIDTH-1:26*WORD_WIDTH];
            6'h1b: out = in[28*WORD_WIDTH-1:27*WORD_WIDTH];
            6'h1c: out = in[29*WORD_WIDTH-1:28*WORD_WIDTH];
            6'h1d: out = in[30*WORD_WIDTH-1:29*WORD_WIDTH];
            6'h1e: out = in[31*WORD_WIDTH-1:30*WORD_WIDTH];
            6'h1f: out = in[32*WORD_WIDTH-1:31*WORD_WIDTH];
            6'h20: out = in[33*WORD_WIDTH-1:32*WORD_WIDTH];
            6'h21: out = in[34*WORD_WIDTH-1:33*WORD_WIDTH];
            6'h22: out = in[35*WORD_WIDTH-1:34*WORD_WIDTH];
            6'h23: out = in[36*WORD_WIDTH-1:35*WORD_WIDTH];
            6'h24: out = in[37*WORD_WIDTH-1:36*WORD_WIDTH];
            6'h25: out = in[38*WORD_WIDTH-1:37*WORD_WIDTH];
            6'h26: out = in[39*WORD_WIDTH-1:38*WORD_WIDTH];
            6'h27: out = in[40*WORD_WIDTH-1:39*WORD_WIDTH];
            default: out = {(WORD_WIDTH){1'bX}};
        endcase
    end
endmodule
module inflight_instr_counter
  (/*AUTOARG*/
   // Outputs
   no_inflight_instr_flag, max_inflight_instr_flag,
   // Inputs
   clk, rst, retire_vgpr_1_en, retire_branch_en, retire_sgpr_en,
   issued_en
   );

   // Inputs and outputs
   input clk,rst, retire_vgpr_1_en, 
	 retire_branch_en, retire_sgpr_en,
	 issued_en;


   output no_inflight_instr_flag, max_inflight_instr_flag;

   wire   wr_en;

   // For now, allow only 16 inflight instructions
   wire [3:0] inflight_instr_counter;

   // This will be used to calculate the total number of retired instructions
   wire [1:0] total_retired_instr;
   wire [2:0] total_counter_summed_value;

   // Next counter value   
   wire [3:0] counter_value;
   wire [3:0] next_counter_value;

   // Find the number of retired instructions
   adder1bit adder_retired 
     (
      total_retired_instr[0],
      total_retired_instr[1],
      retire_vgpr_1_en,
      retire_branch_en,
      retire_sgpr_en
      );

   // Calculates:
   // total_counter_summed_value =  (issued_en? 1 : 0) - total_retired_instr  
   adder_param #(3) adder_issued 
     (
      .in1({{2{1'b0}},issued_en}),
      .in2({1'b1,~total_retired_instr}),
      .cin(1'b1),
      .sum(total_counter_summed_value),
      .cout()
      );

   // Calculates the next counter value
   adder_param #(4) adder_next_counter 
     (
      .in1({total_counter_summed_value[2],total_counter_summed_value}),
      .in2(counter_value),
      .cin(1'b0),
      .sum(next_counter_value),
      .cout()
      );

   // Register for the counter value
   register #(4) counter_reg
     (
      .out(counter_value), 
      .in(next_counter_value), 
      .wr_en(wr_en), 
      .clk(clk), 
      .rst(rst)
      );

   // Finds out when to write the counter
   assign wr_en = retire_vgpr_1_en | retire_branch_en |retire_sgpr_en | issued_en;

   // Calculate the no_inflight_instr bit or the max_inflight_instr_bit
   assign no_inflight_instr_flag = ~(|counter_value);
   assign max_inflight_instr_flag = &counter_value;


endmodule
module arbiter(
    // Inputs
    input_arry,
    issued_en,
    issued_wf_id,
    
    // Outputs
    choosen_valid,
    choosen_wf_id,
    
    clk,
    rst
);

input clk,rst;
input issued_en;
input[5:0] issued_wf_id;
input[39:0] input_arry;

output choosen_valid;
output[5:0] choosen_wf_id;

wire[5:0] last_issued_wf_id, last_issued_wf_id_corr_output, priority_encoder_out;
wire[39:0] priority_encoder_in, decoded_priority_encoder_out, choosen_wf_id_encoded;

reg_param #(6) last_wf_id_issued_reg(
    .out(last_issued_wf_id),
    .in(issued_wf_id),
    .wr_en(issued_en),
    .clk(clk),
    .rst(rst)
);

circular_barrel_shift input_priority_shifter(
	.output_val(priority_encoder_in),
	.input_val(input_arry),
	.shift_amt(last_issued_wf_id)
);

circular_barrel_shift output_priority_shifter(
    .output_val(choosen_wf_id_encoded),
    .input_val(decoded_priority_encoder_out),
    .shift_amt(last_issued_wf_id_corr_output)
);

decoder_6b_40b_en decoder_6b_40b_en(
	.addr_in(priority_encoder_out),
	.out(decoded_priority_encoder_out),
	.en(choosen_valid)
);

priority_encoder_40to6 priority_encoder(
	.binary_out(priority_encoder_out),
	.valid(choosen_valid),
	.encoder_in(priority_encoder_in),
	.enable(|priority_encoder_in)
);

encoder encoder(
	.in(choosen_wf_id_encoded),
	.out(choosen_wf_id)
);

assign last_issued_wf_id_corr_output = 6'd40 - last_issued_wf_id;

endmodule
module branch_wait
  (/*AUTOARG*/
   // Outputs
   pending_branches_arry,
   // Inputs
   clk, rst, alu_valid, alu_branch, alu_wfid, f_salu_branch_en,
   f_salu_branch_wfid
   );
   input clk, rst;

   // Issued alu info
   input alu_valid, alu_branch;   
   input [`WF_ID_LENGTH-1:0] alu_wfid;

   // Salu signals with outcome of branch
   input 		    f_salu_branch_en;
   input [`WF_ID_LENGTH-1:0] f_salu_branch_wfid;

   // Output - list of pending branches
   output [`WF_PER_CU-1:0]   pending_branches_arry;
   
   /**
    * Branch wait is a reg that marks all wf with a pending branch.
    * Pending branches start when a branch instruction is issued
    * and end when salu signals the outcome of the branch
    **/

   wire 		    alu_branch_valid;
   wire [`WF_PER_CU-1:0]     alu_branch_decoded, 
			    salu_branch_decoded;

   wire [`WF_PER_CU-1:0]     pending_branch, next_pending_branch;

   assign pending_branches_arry = pending_branch;
   
   // Decoder for the issued branch
   decoder_6b_40b_en alu_brach_decoder
     (
      .addr_in(alu_wfid),
      .out(alu_branch_decoded),
      .en(alu_branch_valid)
      );

   // Decoder for the finished branch by fetch
   decoder_6b_40b_en issue_Value_decoder
     (
      .addr_in(f_salu_branch_wfid),
      .out(salu_branch_decoded),
      .en(f_salu_branch_en)
      );

   dff pending_branch_ff[`WF_PER_CU-1:0]
     (
      .q(pending_branch),
      .d(next_pending_branch),
      .clk(clk),
      .rst(rst)
      );
   
   assign alu_branch_valid = alu_valid && alu_branch; 
   assign next_pending_branch 
     = (  pending_branch | (alu_branch_decoded)  ) &
       ~(salu_branch_decoded);
   
endmodule
module valid_entry
  (/*AUTOARG*/
   // Outputs
   valid_entry_out,
   // Inputs
   clk, rst, f_decode_valid, f_decode_wf_halt, f_decode_barrier,
   f_salu_branch_en, f_salu_branch_taken, issued_valid,
   f_decode_waitcnt, f_decode_wfid, issued_wfid, f_salu_branch_wfid
   );

   // Valid entry is set at decode and cleared at issue

   input clk,rst;
   input f_decode_valid, f_decode_wf_halt, f_decode_barrier, 
	 f_salu_branch_en, f_salu_branch_taken, issued_valid,
	 f_decode_waitcnt;
   input [`WF_ID_LENGTH-1:0] f_decode_wfid, issued_wfid, 
			     f_salu_branch_wfid;
   
   wire 		     decode_init_en;
   wire [`WF_PER_CU-1:0]     decoded_init_instr, decoded_issued,
			     decoded_branch_taken,
			     next_valid_entry;

   output [`WF_PER_CU-1:0]   valid_entry_out;

   decoder_6b_40b_en init_instr_decoder(
					.addr_in(f_decode_wfid),
					.out(decoded_init_instr),
					.en(decode_init_en)
					);

   decoder_6b_40b_en instr_issued_decoder(
				       .addr_in(issued_wfid),
				       .out(decoded_issued),
				       .en(issued_valid)
				       );

   decoder_6b_40b_en branch_taken_decoder(
				       .addr_in(f_salu_branch_wfid),
				       .out(decoded_branch_taken),
				       .en((f_salu_branch_en & f_salu_branch_taken))
				       );

   dff valid_reg[`WF_PER_CU-1:0] 
     (
      .q(valid_entry_out),
      .d(next_valid_entry),
      .clk(clk),
      .rst(rst)
      );

   assign decode_init_en = f_decode_valid & ~f_decode_wf_halt & ~f_decode_barrier & ~f_decode_waitcnt;
   
   assign next_valid_entry = (valid_entry_out | (decoded_init_instr)) & 
			     ~(decoded_issued | decoded_branch_taken);
   
   
endmodule
module issue_flow_control
  (/*AUTOARG*/
   // Outputs
   wave_valid_entries,
   // Inputs
   clk, rst, tracemon_barrier_retire_en, valid_entry_out,
   tracemon_barrier_retire_wf_bitmap, f_decode_wfid,
   f_salu_branch_wfid, alu_wfid, f_decode_valid, f_decode_waitcnt,
   f_salu_branch_en, alu_valid, alu_branch
   );

   input clk,rst;
   input tracemon_barrier_retire_en;
   input [`WF_PER_CU-1:0] valid_entry_out;
   input [`WF_PER_CU-1:0] tracemon_barrier_retire_wf_bitmap;
   input [`WF_ID_LENGTH-1:0] f_decode_wfid, f_salu_branch_wfid,
			     alu_wfid;
   input 		     f_decode_valid, f_decode_waitcnt,
			     f_salu_branch_en,
			     alu_valid, alu_branch;

   wire [`WF_PER_CU-1:0]     flopped_valid_entry_out;
   wire [`WF_PER_CU-1:0]     valid_barrier_retire_wf_bitmap;
   wire [`WF_PER_CU-1:0]     decoded_decode_waitcnt, decoded_branch_retired;
			     
   wire [`WF_PER_CU-1:0]     decoded_branch_issued, flopped_decoded_branch_issued;
   
			
   output [`WF_PER_CU-1:0]   wave_valid_entries;


   decoder_6b_40b_en branch_issue
     (
      .addr_in(alu_wfid),
      .out(decoded_branch_issued),
      .en(alu_valid & alu_branch)
      );
   
   decoder_6b_40b_en branch_retire
     (
      .addr_in(f_salu_branch_wfid),
      .out(decoded_branch_retired),
      .en(f_salu_branch_en)
      );
   
   decoder_6b_40b_en wait_cnt_decoder
     (
      .addr_in(f_decode_wfid),
      .out(decoded_decode_waitcnt),
      .en(f_decode_valid & f_decode_waitcnt)
      );

   dff valid_entry_out_flop[`WF_PER_CU-1:0]
     (
      .q(flopped_valid_entry_out),
      .d(valid_entry_out),
      .clk(clk),
      .rst(rst)
      );

   dff branch_issued_flop[`WF_PER_CU-1:0]
     (
      .q(flopped_decoded_branch_issued),
      .d(decoded_branch_issued),
      .clk(clk),
      .rst(rst)
      );

   assign valid_barrier_retire_wf_bitmap 
     = ( tracemon_barrier_retire_en )? tracemon_barrier_retire_wf_bitmap : 
       {`WF_PER_CU{1'b0}};

   // Ask for new instructions when valid goes down (instruction is issued) or when
   // a barrier or a branch of a waitcnt retire.
   // Do not ask for new instructions when a branch was issued last cycle
   assign wave_valid_entries 
     = (  ( (valid_entry_out ^ flopped_valid_entry_out) & flopped_valid_entry_out ) | 
	  valid_barrier_retire_wf_bitmap | decoded_decode_waitcnt | decoded_branch_retired  ) &
       ~flopped_decoded_branch_issued;   
endmodule
module circular_barrel_shift_9b(
    output_val,
    input_val,
    shift_amt
);

output[8:0] output_val;

input[8:0] input_val;
input[3:0] shift_amt;

wire[8:0] shift_1, shift_2, shift_4, shift_8, shift_16; 

assign shift_1  = shift_amt[0] ? (input_val >> 1 | input_val << 8) : input_val;
assign shift_2  = shift_amt[1] ? (shift_1 >> 2 | shift_1 << 7) : shift_1;
assign shift_4  = shift_amt[2] ? (shift_2 >> 4 | shift_2 << 5) : shift_2;
assign output_val = shift_amt[3] ? (shift_4 >>  8 | shift_4 << 1) : shift_4;

endmodule
module mem_wait
(/*AUTOARG*/
    // Outputs
    mem_wait_arry,
    // Inputs
    clk, rst, lsu_valid, lsu_done,
    lsu_wfid, lsu_done_wfid
);

input clk,rst;
input lsu_valid, lsu_done;
input [5:0] lsu_wfid, lsu_done_wfid;

output [`WF_PER_CU-1:0] mem_wait_arry;

wire [`WF_PER_CU-1:0]   decoded_issue_value, decoded_lsu_retire_value,
                        mem_wait_reg_wr_en, mem_waiting_wf;

decoder_6b_40b_en issue_value_decoder
(
    .addr_in(lsu_wfid),
    .out(decoded_issue_value),
    .en(lsu_valid)
);


decoder_6b_40b_en retire_lsu_value_decoder
(
    .addr_in(lsu_done_wfid),
    .out(decoded_lsu_retire_value),
    .en(lsu_done)
);

dff_set_en_rst mem_wait[`WF_PER_CU-1:0]
(
    .q(mem_waiting_wf),
    .d(40'b0),
    .en(mem_wait_reg_wr_en),
    .clk(clk),
    .set(decoded_issue_value),
    .rst(rst)
);

assign mem_wait_reg_wr_en = decoded_lsu_retire_value | decoded_issue_value;

assign mem_wait_arry = mem_waiting_wf;
endmodule
module memory(
      gm_or_lds,
      rd_en,
      wr_en,
      addresses,
      wr_data,
      input_tag,
//      wr_mask,
      rd_data,
      output_tag,
      ack,
      clk,
      rst
 );

input clk;
input rst;

input gm_or_lds;
input rd_en, wr_en;
input [31:0] addresses;
input [31:0] wr_data;
input [6:0] input_tag;

output [6:0] output_tag;
output ack;
output [31:0] rd_data;

reg[7:0] data_memory[50000:0];
reg[7:0] lds_memory[65535:0];

reg ack_reg;
reg [6:0] tag_reg;

//integer locrd = 4; // num of loc to read

assign ack = ack_reg;
assign output_tag = tag_reg;
integer i;
always@(posedge clk, posedge rst) begin
      // if(rst) begin
      //       for(i = 0; i < 50001; i = i+1) begin
      //             data_memory[i] <= 0;
      //       end
      //       for(i = 0; i < 65536; i = i+1) begin
      //             lds_memory[i] <= 0;
      //       end
      // end
      // else 
      if(wr_en) begin
            if(gm_or_lds) begin
                  lds_memory [addresses] <= wr_data[7:0];
                  lds_memory [addresses+1] <= wr_data[15:7];
                  lds_memory [addresses+2] <= wr_data[23:16];
                  lds_memory [addresses+3] <= wr_data[31:24];
            end
            else begin
                  data_memory [addresses] <= wr_data[7:0];
                  data_memory [addresses+1] <= wr_data[15:7];
                  data_memory [addresses+2] <= wr_data[23:16];
                  data_memory [addresses+3] <= wr_data[31:24];
            end
      end
end

always@(posedge clk) begin
  if(rst) begin
    ack_reg <= 1'b0;
    tag_reg <= 7'd0;
  end
  else begin
    ack_reg <= 1'b0;
    tag_reg <= 7'd0;
    if(rd_en | wr_en) begin
      ack_reg <= 1'b1;
      tag_reg <= input_tag;
    end
  end
end

wire [31:0] rd_lds;
wire [31:0] rd_dm;
assign rd_lds = {lds_memory[addresses+3],lds_memory[addresses+2],lds_memory[addresses+1],lds_memory[addresses]};
assign rd_dm = {data_memory[addresses+3],data_memory[addresses+2],data_memory[addresses+1],data_memory[addresses]};

assign rd_data = (gm_or_lds) ? rd_lds:rd_dm;

endmodule
module src_mux (
 src_constant,
 sgpr_rd_data,
 vgpr_source_data,
 exec_rd_exec_value,
 exec_rd_vcc_value,
 exec_rd_m0_value,
 exec_rd_scc_value,
 literal_constant,
 source_mux_select,
 source_data
);

input [9:0] src_constant;
input [31:0] sgpr_rd_data;
input [2047:0] vgpr_source_data;
input [63:0] exec_rd_exec_value;
input [63:0] exec_rd_vcc_value;
input [31:0] exec_rd_m0_value;
input exec_rd_scc_value;
input [3:0] source_mux_select;
input [31:0] literal_constant;
output [2047:0] source_data;

reg [2047:0] source_data;

always @ (src_constant or sgpr_rd_data or
 vgpr_source_data or exec_rd_exec_value or
 exec_rd_vcc_value or source_mux_select or literal_constant) begin

	casex(source_mux_select)
		4'b0000 : source_data <= {64{literal_constant}};
		4'b0001 : source_data <= {64{{22{src_constant[9]}}, src_constant}};
		4'b0010 : source_data <= vgpr_source_data;
		4'b0011 : source_data <= {64{sgpr_rd_data}};
		4'b0100 : source_data <= {64{exec_rd_vcc_value[31:0]}};
		4'b0101 : source_data <= {64{exec_rd_vcc_value[63:32]}};
		4'b0110 : source_data <= {64{exec_rd_m0_value}};
		4'b0111 : source_data <= {64{exec_rd_exec_value[31:0]}};
		4'b1000 : source_data <= {64{exec_rd_exec_value[63:32]}};
		4'b1001 : source_data <= {64{31'b0, !(&exec_rd_vcc_value)}};
		4'b1010 : source_data <= {64{31'b0, !(&exec_rd_exec_value)}};
		4'b1011 : source_data <= {64{31'b0, exec_rd_scc_value}};
		default: source_data <= {2048{1'bx}};
	endcase
end

endmodule
module mux_2_to_1 (out, in, select);

  parameter WIDTH = 1;
  output [WIDTH-1:0] out;
  input [(2*WIDTH)-1:0] in;
  input select;

  reg [WIDTH-1:0] out;

  always @ (in or select) begin
    casex(select)
      1'b0: out <= in[WIDTH-1:0];
      1'b1: out <= in[(2*WIDTH)-1:WIDTH];
      default: out <= {WIDTH{1'bx}};
    endcase
  end
endmodule
module alu_fsm (
 in_alu_select,
 out_alu_start,
 in_valu_done,
 out_alu_ready,
 RD,
 EX,
 WB,
 clk,
 rst
);

input in_alu_select;
input in_valu_done;

output out_alu_start;
output out_alu_ready;
output RD;
output EX;
output WB;

input clk;
input rst;

reg out_alu_ready;
reg RD;
reg WB;
reg [2:0] next_state;
reg next_EX;
reg next_alu_start;

wire [2:0] current_state;

dff state_flop[2:0] (.q(current_state), .d(next_state), .clk(clk), .rst(rst));
dff EX_flop (.q(EX), .d(next_EX), .clk(clk), .rst(rst));
dff alu_start_flop (.q(out_alu_start), .d(next_alu_start), .clk(clk), .rst(rst));

always @ (current_state or in_alu_select or in_valu_done) begin
	casex({current_state, in_alu_select, in_valu_done})
		{`IDLE, 1'b0, 1'b0} :
			begin
				next_state <= `IDLE;
				out_alu_ready <= 1'b1;
				RD <= 1'b0;
				next_EX <= 1'b0;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`IDLE, 1'b1, 1'b0} :
			begin
				next_state <= `STATE_EX1;
				out_alu_ready <= 1'b0;
				RD <= 1'b1;
				next_EX <= 1'b1;
				next_alu_start <= 1'b1;
				WB <= 1'b0;
			end
		{`STATE_RD, 1'b0, 1'b?} :
			begin
				next_state <= `STATE_EX1;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`STATE_EX1, 1'b0, 1'b0} :
			begin
				next_state <= `STATE_EX1;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`STATE_EX1, 1'b0, 1'b1} :
			begin
				next_state <= `STATE_EX2;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b1;
				WB <= 1'b0;
			end
		{`STATE_EX2, 1'b0, 1'b0} :
			begin
				next_state <= `STATE_EX2;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`STATE_EX2, 1'b0, 1'b1} :
			begin
				next_state <= `STATE_EX3;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b1;
				WB <= 1'b0;
			end
		{`STATE_EX3, 1'b0, 1'b0} :
			begin
				next_state <= `STATE_EX3;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`STATE_EX3, 1'b0, 1'b1} :
			begin
				next_state <= `STATE_EX4;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b1;
				WB <= 1'b0;
			end
		{`STATE_EX4, 1'b0, 1'b0} :
			begin
				next_state <= `STATE_EX4;
				out_alu_ready <= 1'b0;
				RD <= 1'b0;
				next_EX <= 1'b1;
				next_alu_start <= 1'b0;
				WB <= 1'b0;
			end
		{`STATE_EX4, 1'b0, 1'b1} :
			begin
				next_state <= `IDLE;
				out_alu_ready <= 1'b1;
				RD <= 1'b0;
				next_EX <= 1'b0;
				next_alu_start <= 1'b0;
				WB <= 1'b1;
			end
		default :
			begin
				next_state <= 3'bxxx;
				out_alu_ready <= 1'bx;
				RD <= 1'bx;
				next_EX <= 1'bx;
				next_alu_start <= 1'bx;
				WB <= 1'bx;
			end
	endcase
end

endmodule
module shift_in (
 data_in,
 wr_en,
 shift_en,
 data_out,
 clk,
 rst
);

parameter WIDTH=1;

input [(64*WIDTH)-1:0] data_in;
input wr_en;
input shift_en;
output [(16*WIDTH)-1:0] data_out;
input clk;
input rst;

wire [(64*WIDTH)-1:0] reg_in;
wire [(64*WIDTH)-1:0] reg_out;
reg line_wr_en;
reg s_or_w_;

always @ (shift_en or wr_en)
begin
  casex({shift_en,wr_en})
    2'b00:
      begin
        line_wr_en <= 1'b0;
        s_or_w_ <= 1'bx;
      end
    2'b01:
      begin
        line_wr_en <= 1'b1;
        s_or_w_ <= 1'b0;
      end
    2'b10:
      begin
        line_wr_en <= 1'b1;
        s_or_w_ <= 1'b1;
      end
    default:
      begin
        line_wr_en <= 1'bx;
        s_or_w_ <= 1'bx;
      end
  endcase
end

register #(WIDTH*16) reg_line[3:0](.out(reg_out), .in(reg_in), .wr_en(line_wr_en), .clk(clk), .rst(rst));

mux_2_to_1 #(WIDTH*16) line3_mux(.out(reg_in[(WIDTH*64)-1:(WIDTH*48)]), .in({{WIDTH*16{1'bx}},data_in[(WIDTH*64)-1:(WIDTH*48)]}), .select(s_or_w_));
mux_2_to_1 #(WIDTH*16) line2_mux(.out(reg_in[(WIDTH*48)-1:(WIDTH*32)]), .in({reg_out[(WIDTH*64)-1:WIDTH*48],data_in[(WIDTH*48)-1:(WIDTH*32)]}), .select(s_or_w_));
mux_2_to_1 #(WIDTH*16) line1_mux(.out(reg_in[(WIDTH*32)-1:(WIDTH*16)]), .in({reg_out[(WIDTH*48)-1:WIDTH*32],data_in[(WIDTH*32)-1:(WIDTH*16)]}), .select(s_or_w_));
mux_2_to_1 #(WIDTH*16) line0_mux(.out(reg_in[(WIDTH*16)-1:0]), .in({reg_out[(WIDTH*32)-1:WIDTH*16],data_in[(WIDTH*16)-1:0]}), .select(s_or_w_));

assign data_out = reg_out[(WIDTH*16)-1:0];

endmodule
module dest_shift_reg (
 alu_vgpr_dest_data,
 alu_sgpr_dest_data,
 alu_dest_vcc_value,
 alu_dest_exec_value,
 dest_buffer_wr_en,
 dest_buffer_shift_en,
 vgpr_dest_data,
 sgpr_dest_data,
 exec_wr_vcc_value,
 vgpr_wr_mask,
 clk,
 rst
);

input [511:0]   alu_vgpr_dest_data;
input [15:0]    alu_sgpr_dest_data;
input [15:0]    alu_dest_vcc_value;
input [15:0]    alu_dest_exec_value;
input           dest_buffer_wr_en;
input           dest_buffer_shift_en;
output [2047:0] vgpr_dest_data;
output [63:0]   sgpr_dest_data;
output [63:0]   exec_wr_vcc_value;
output [63:0]   vgpr_wr_mask;
input           clk;
input           rst;

shift_out #(32) vgpr_dest_shift(
  .data_in(alu_vgpr_dest_data),
  .wr_en(dest_buffer_wr_en),
  .shift_en(dest_buffer_shift_en),
  .data_out(vgpr_dest_data),
  .clk(clk),
  .rst(rst)
);

shift_out #(1) sgpr_dest_shift(
  .data_in(alu_sgpr_dest_data),
  .wr_en(dest_buffer_wr_en),
  .shift_en(dest_buffer_shift_en),
  .data_out(sgpr_dest_data),
  .clk(clk),
  .rst(rst)
);

shift_out #(1) exec_shift(
  .data_in(alu_dest_exec_value),
  .wr_en(dest_buffer_wr_en),
  .shift_en(dest_buffer_shift_en),
  .data_out(vgpr_wr_mask),
  .clk(clk),
  .rst(rst)
);

shift_out #(1) vcc_shift(
  .data_in(alu_dest_vcc_value),
  .wr_en(dest_buffer_wr_en),
  .shift_en(dest_buffer_shift_en),
  .data_out(exec_wr_vcc_value),
  .clk(clk),
  .rst(rst)
);

endmodule
module PS_flops_EX_WB_alu (
 in_wfid,
 in_instr_pc,
 in_vgpr_dest_addr,
 in_sgpr_dest_addr,
 in_instr_done,
 in_vgpr_wr_en,
 in_sgpr_wr_en,
 in_vcc_wr_en,
 out_wfid,
 out_instr_pc,
 out_vgpr_dest_addr,
 out_sgpr_dest_addr,
 out_instr_done,
 out_vgpr_dest_wr_en,
 out_sgpr_dest_wr_en,
 out_vcc_wr_en,
 clk,
 rst
);

input [5:0] in_wfid;
input [31:0] in_instr_pc;
input [9:0] in_vgpr_dest_addr;
input [8:0] in_sgpr_dest_addr;
input in_instr_done;
input in_vgpr_wr_en;
input in_sgpr_wr_en;
input in_vcc_wr_en;

output [5:0] out_wfid;
output [31:0] out_instr_pc;
output [9:0] out_vgpr_dest_addr;
output [8:0] out_sgpr_dest_addr;
output out_instr_done;
output out_vgpr_dest_wr_en;
output out_sgpr_dest_wr_en;
output out_vcc_wr_en;

input clk;
input rst;

dff flop_wfid[5:0] (.q(out_wfid), .d(in_wfid), .clk(clk), .rst(rst));
dff flop_instr_pc[31:0] (.q(out_instr_pc), .d(in_instr_pc), .clk(clk), .rst(rst));
dff flop_vgpr_dest_addr[9:0] (.q(out_vgpr_dest_addr), .d(in_vgpr_dest_addr), .clk(clk), .rst(rst));
dff flop_sgpr_dest_addr[8:0] (.q(out_sgpr_dest_addr), .d(in_sgpr_dest_addr), .clk(clk), .rst(rst));
dff flop_instr_done (.q(out_instr_done), .d(in_instr_done), .clk(clk), .rst(rst));
dff flop_vgpr_wr_en (.q(out_vgpr_dest_wr_en), .d(in_vgpr_wr_en), .clk(clk), .rst(rst));
dff flop_sgpr_wr_en (.q(out_sgpr_dest_wr_en), .d(in_sgpr_wr_en), .clk(clk), .rst(rst));
dff flop_vcc_wr_en (.q(out_vcc_wr_en), .d(in_vcc_wr_en), .clk(clk), .rst(rst));

endmodule
module shift_out (
 data_in,
 wr_en,
 shift_en,
 data_out,
 clk,
 rst
);

parameter WIDTH=1;

input [(16*WIDTH)-1:0] data_in;
input wr_en;
input shift_en;
output [(64*WIDTH)-1:0] data_out;
input clk;
input rst;

wire [(64*WIDTH)-1:0] reg_in;
wire [3:0] line_wr_en;

assign reg_in[(WIDTH*16)-1:0] = data_out[(WIDTH*32)-1:(WIDTH*16)];
assign reg_in[(WIDTH*32)-1:(WIDTH*16)] = data_out[(WIDTH*48)-1:(WIDTH*32)];
assign reg_in[(WIDTH*48)-1:(WIDTH*32)] = data_out[(WIDTH*64)-1:(WIDTH*48)];
assign reg_in[(WIDTH*64)-1:(WIDTH*48)] = data_in;

assign line_wr_en[0:0] = wr_en;
assign line_wr_en[3:1] = {3{shift_en}};

register #(WIDTH*16) reg_line[3:0](.out(data_out), .in(reg_in), .wr_en(line_wr_en), .clk(clk), .rst(rst));

endmodule
module PS_flops_issue_alu (/*AUTOARG*/
   // Outputs
   out_alu_select, out_wfid, out_instr_pc, out_opcode, out_imm_value0,
   out_imm_value1, out_dest1_addr, out_dest2_addr,
   // Inputs
   in_alu_select, in_wfid, in_instr_pc, in_opcode, in_imm_value0,
   in_imm_value1, in_dest1_addr, in_dest2_addr, clk, rst
   );

input in_alu_select;
input [5:0] in_wfid;
input [31:0] in_instr_pc;
input [31:0] in_opcode;
input [15:0] in_imm_value0;
input [31:0] in_imm_value1;
input [11:0] in_dest1_addr;
input [11:0] in_dest2_addr;

output out_alu_select;
output [5:0]  out_wfid;
output [31:0] out_instr_pc;
output [31:0] out_opcode;
output [15:0] out_imm_value0;
output [31:0] out_imm_value1;
output [11:0] out_dest1_addr;
output [11:0] out_dest2_addr;

input clk;
input rst;

dff_en flop_alu_select (.q(out_alu_select), .d(in_alu_select), .en(1'b1), .clk(clk), .rst(rst));
dff_en flop_wfid[5:0] (.q(out_wfid), .d(in_wfid), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_instr_pc[31:0] (.q(out_instr_pc), .d(in_instr_pc), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_opcode[31:0] (.q(out_opcode), .d(in_opcode), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_imm_value0[15:0] (.q(out_imm_value0), .d(in_imm_value0), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_imm_value1[31:0] (.q(out_imm_value1), .d(in_imm_value1), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_dest1_addr[11:0] (.q(out_dest1_addr), .d(in_dest1_addr), .en(in_alu_select), .clk(clk), .rst(rst));
dff_en flop_dest2_addr[11:0] (.q(out_dest2_addr), .d(in_dest2_addr), .en(in_alu_select), .clk(clk), .rst(rst));

endmodule
module src_shift_reg (
 source1_data,
 source2_data,
 source3_data,
 source_vcc_value,
 source_exec_value,
 src_buffer_wr_en,
 src_buffer_shift_en,
 alu_source1_data,
 alu_source2_data,
 alu_source3_data,
 alu_source_vcc_value,
 alu_source_exec_value,
 clk,
 rst
);

input [2047:0] source1_data;
input [2047:0] source2_data;
input [2047:0] source3_data;
input [63:0]   source_vcc_value;
input [63:0]   source_exec_value;
input          src_buffer_wr_en;
input          src_buffer_shift_en;
output [511:0] alu_source1_data;
output [511:0] alu_source2_data;
output [511:0] alu_source3_data;
output [15:0]  alu_source_vcc_value;
output [15:0]  alu_source_exec_value;
input          clk;
input          rst;

shift_in #(32) src1_shift(
  .data_in(source1_data),
  .wr_en(src_buffer_wr_en),
  .shift_en(src_buffer_shift_en),
  .data_out(alu_source1_data),
  .clk(clk),
  .rst(rst)
);

shift_in #(32) src2_shift(
  .data_in(source2_data),
  .wr_en(src_buffer_wr_en),
  .shift_en(src_buffer_shift_en),
  .data_out(alu_source2_data),
  .clk(clk),
  .rst(rst)
);

shift_in #(32) src3_shift(
  .data_in(source3_data),
  .wr_en(src_buffer_wr_en),
  .shift_en(src_buffer_shift_en),
  .data_out(alu_source3_data),
  .clk(clk),
  .rst(rst)
);

shift_in #(1) exec_shift(
  .data_in(source_exec_value),
  .wr_en(src_buffer_wr_en),
  .shift_en(src_buffer_shift_en),
  .data_out(alu_source_exec_value),
  .clk(clk),
  .rst(rst)
);

shift_in #(1) vcc_shift(
  .data_in(source_vcc_value),
  .wr_en(src_buffer_wr_en),
  .shift_en(src_buffer_shift_en),
  .data_out(alu_source_vcc_value),
  .clk(clk),
  .rst(rst)
);

endmodule
module priority_encoder_16_to_4 (
   out,
   in,
   enable
);

output[3:0] out;
input[15:0] in;
input enable;

assign out =
      (!enable) ? 4'd0 : (
      (in[0]) ? 4'd0 :
      (in[1]) ? 4'd1 :
      (in[2]) ? 4'd2 :
      (in[3]) ? 4'd3 :
      (in[4]) ? 4'd4 :
      (in[5]) ? 4'd5 :
      (in[6]) ? 4'd6 :
      (in[7]) ? 4'd7 :
      (in[8]) ? 4'd8 :
      (in[9]) ? 4'd9 :
      (in[10]) ? 4'd10 :
      (in[11]) ? 4'd11 :
      (in[12]) ? 4'd12 :
      (in[13]) ? 4'd13 :
      (in[14]) ? 4'd14 :
      (in[15]) ? 4'd15 :  {4{1'bx}});

endmodule
module circular_shift (
   out,
   in,
   shift_amount
);

output[15:0] out;

input[15:0] in;
input[3:0] shift_amount;

wire[15:0] shift_1, shift_2, shift_4;

assign shift_1  = shift_amount[0] ? (in >> 1 | in << 15) : in;
assign shift_2  = shift_amount[1] ? (shift_1 >> 2 | shift_1 << 14) : shift_1;
assign shift_4  = shift_amount[2] ? (shift_2 >> 4 | shift_2 << 12) : shift_2;
assign out  = shift_amount[3] ? (shift_4 >> 8 | shift_4 << 8) : shift_4;

endmodule
module flop (q, d, clk);

   output         q;
   input          d;
   input          clk;
   reg            state;

   assign q = state;

   always @(posedge clk)
   begin
      state <= d;
   end

`ifdef dump_flops
   always @(posedge gpu_tb.rst)
   begin
      if ($test$plusargs("dump_flops"))
      begin
         $display("%m.state");
      end
   end
`endif
endmodule
module dff_set (q, d, clk, set);

   output         q;
   input          d;
   input          clk;
   input          set;

   reg            state;

   assign q = state;

   always @(posedge clk)
   begin
      state <= set? 1 : d;
   end

`ifdef dump_flops
   always @(posedge gpu_tb.rst)
   begin
      if ($test$plusargs("dump_flops"))
      begin
         $display("%m.state");
      end
   end
`endif
endmodule
module reg_32b (out, in, wr_en, clk, rst);

  output [31:0] out;
  input [31:0] in;
  input wr_en;
  input clk;
  input rst;

  dff_en bits[31:0] (.q(out), .d(in), .en(wr_en), .clk(clk), .rst(rst));

endmodule
module decoder_param (out, in);

   parameter BITS = 2;
   parameter SIZE = 4;

   output [SIZE - 1:0] out;
   input [BITS - 1:0] in;

   reg [SIZE -1: 0] out;
   integer i;

   always @ (in)
      begin
         for(i = 0; i < SIZE; i = i + 1)
         begin
            out[i] = (in == i) ? 1'b1 : 1'b0;
         end
      end

endmodule
module not1 (in1,out);
input in1;
output out;
assign out = ~in1;
endmodule
module reg_param (out, in, wr_en, clk, rst);

parameter WIDTH = 2;

  output[WIDTH-1:0] out;
  input[WIDTH-1:0] in;
  input wr_en;
  input clk;
  input rst;

  dff_en bits[WIDTH - 1:0] (.q(out), .d(in), .en(wr_en), .clk(clk), .rst(rst));

endmodule
module decoder_6b_40b_en(
    addr_in,
    en,
    out);

input[5:0] addr_in; 
wire[5:0] addr_in;

output[39:0] out;
wire[39:0] out;
input en; 
wire en;

reg[39:0] decoded_out;

always@(addr_in)
begin
    decoded_out = 40'd0;
    case (addr_in)
        0: decoded_out[0]=1'b1;
        1: decoded_out[1]=1'b1;
        2: decoded_out[2]=1'b1;
        3: decoded_out[3]=1'b1;
        4: decoded_out[4]=1'b1;
        5: decoded_out[5]=1'b1;
        6: decoded_out[6]=1'b1;
        7: decoded_out[7]=1'b1;
        8: decoded_out[8]=1'b1;
        9: decoded_out[9]=1'b1;
        10: decoded_out[10]=1'b1;
        11: decoded_out[11]=1'b1;
        12: decoded_out[12]=1'b1;
        13: decoded_out[13]=1'b1;
        14: decoded_out[14]=1'b1;
        15: decoded_out[15]=1'b1;
        16: decoded_out[16]=1'b1;
        17: decoded_out[17]=1'b1;
        18: decoded_out[18]=1'b1;
        19: decoded_out[19]=1'b1;
        20: decoded_out[20]=1'b1;
        21: decoded_out[21]=1'b1;
        22: decoded_out[22]=1'b1;
        23: decoded_out[23]=1'b1;
        24: decoded_out[24]=1'b1;
        25: decoded_out[25]=1'b1;
        26: decoded_out[26]=1'b1;
        27: decoded_out[27]=1'b1;
        28: decoded_out[28]=1'b1;
        29: decoded_out[29]=1'b1;
        30: decoded_out[30]=1'b1;
        31: decoded_out[31]=1'b1;
        32: decoded_out[32]=1'b1;
        33: decoded_out[33]=1'b1;
        34: decoded_out[34]=1'b1;
        35: decoded_out[35]=1'b1;
        36: decoded_out[36]=1'b1;
        37: decoded_out[37]=1'b1;
        38: decoded_out[38]=1'b1;
        39: decoded_out[39]=1'b1;
        default: decoded_out = 40'd0;
    endcase
end

assign out = (en)?decoded_out:40'd0;

endmodule
module circular_barrel_shift (
	output_val,
	input_val,
	shift_amt
);

output[39:0] output_val;

input[39:0] input_val;
input[5:0] shift_amt;

wire[39:0] shift_1, shift_2, shift_4, shift_8, shift_16; 

assign shift_1  = shift_amt[0] ? (input_val >> 1 | input_val << 39) : input_val;
assign shift_2  = shift_amt[1] ? (shift_1 >> 2 | shift_1 << 38) : shift_1;
assign shift_4  = shift_amt[2] ? (shift_2 >> 4 | shift_2 << 36) : shift_2;
assign shift_8  = shift_amt[3] ? (shift_4 >> 8 | shift_4 << 32) : shift_4;
assign shift_16 = shift_amt[4] ? (shift_8 >> 16 | shift_8 << 24) : shift_8;
assign output_val = shift_amt[5] ? (shift_16 >> 32 | shift_16 << 8) : shift_16;

endmodule
module adder_param(
    in1,
    in2,
    cin,
    sum,
    cout
);

parameter WIDTH = 32;

input cin;
input[WIDTH-1:0] in1,in2;
output[WIDTH-1:0] sum;
output cout;

wire[WIDTH-1:0] cout_adders;

adder1bit adders[WIDTH-1:0](
	.sum(sum),
	.cout(cout_adders),
	.in1(in1),
	.in2(in2),
	.cin({cout_adders[WIDTH-2:0],cin})
);

assign cout = cout_adders[WIDTH-1];

endmodule
module flop_32b (out, in, wr_en, clk);

  output [31:0] out;
  input [31:0] in;
  input wr_en;
  input clk;

  flop_en bits[31:0] (.q(out), .d(in), .en(wr_en), .clk(clk));

endmodule
module reg_64b (out, in, wr_en, clk, rst);

  output [63:0] out;
  input [63:0] in;
  input wr_en;
  input clk;
  input rst;

  dff_en bits[63:0] (.q(out), .d(in), .en(wr_en), .clk(clk), .rst(rst));

endmodule
module mux2_1(InA,InB,S,out);
input InA,InB,S;
output out;
wire a1,a2,n1;

not1 n5(S,n1);
nand2 n4(InA,n1,a1);
nand2 n2(InB,S,a2);
nand2 n3(a1,a2,out);

endmodule