// Copyright 2023 Google LLC
// Copyright lowRISC contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * DMA Engine
 *
 * The this module acts as a gasket for Antmicro's fastVDMA, modified to
 * support TLUL as a front-end.
 */

module dma
(
  input  logic                  clk_i,
  input  logic                  rst_ni,

  // Reader Interface
  output tlul_pkg::tl_h2d_t     reader_tl_h_o,
  input  tlul_pkg::tl_d2h_t     reader_tl_h_i,

  // Writer Interface
  output tlul_pkg::tl_h2d_t     writer_tl_h_o,
  input  tlul_pkg::tl_d2h_t     writer_tl_h_i,

  // Control Interface
  input  tlul_pkg::tl_h2d_t     tl_d_i,
  output tlul_pkg::tl_d2h_t     tl_d_o,

  // Interrupt Outputs
  output  logic                 intr_reader_done_o,
  output  logic                 intr_writer_done_o

);

  import top_pkg::*;
  import tlul_pkg::*;

  logic [2:0]       dma_control_d_opcode;
  logic [2:0]       dma_read_a_opcode;
  logic [2:0]       dma_write_a_opcode;

  logic             a_ack;
  logic             wr_req;
  logic             addr_align_err;
  logic             meta_data_err;
  logic             tl_err;
  logic             error, error_int;

  assign a_ack  = tl_d_i.a_valid & tl_d_o.a_ready;
  assign wr_req = a_ack & ((tl_d_i.a_opcode == PutFullData) | (tl_d_i.a_opcode == PutPartialData));

  assign reader_tl_h_o_pre.a_opcode = tlul_pkg::tl_a_op_e'(dma_read_a_opcode);
  assign writer_tl_h_o_pre.a_opcode = tlul_pkg::tl_a_op_e'(dma_write_a_opcode);

  // Controller integrity checks
  logic ctl_intg_err;
  tlul_cmd_intg_chk ctl_chk(
    .tl_i(tl_d_i),
    .err_o(ctl_intg_err)
  );

  assign error_int = ctl_intg_err || addr_align_err || meta_data_err || tl_err;
  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      error <= 1'b0;
    end else if (a_ack) begin
      error <= error_int;
    end
  end

  tlul_pkg::tl_d2h_t tl_d_o_pre;
  assign tl_d_o_pre.d_opcode = tlul_pkg::tl_d_op_e'(dma_control_d_opcode);
  assign tl_d_o_pre.d_user = '{default: '0};
  assign tl_d_o_pre.d_error = error;

  tlul_rsp_intg_gen #(
  ) u_ctl_rsp_intg_gen (
    .tl_i(tl_d_o_pre),
    .tl_o(tl_d_o)
  );


  // Reader integrity checks
  logic reader_intg_err;
  tlul_rsp_intg_chk reader_chk(
    .tl_i(reader_tl_h_i),
    .err_o(reader_intg_err)
  );

  tlul_pkg::tl_h2d_t reader_tl_h_o_pre;
  tlul_cmd_intg_gen #(
  ) u_reader_cmd_intg_gen (
    .tl_i(reader_tl_h_o_pre),
    .tl_o(reader_tl_h_o)
  );


  // Writer integrity checks
  logic writer_intg_err;
  tlul_rsp_intg_chk writer_chk(
    .tl_i(writer_tl_h_i),
    .err_o(writer_intg_err)
  );

  tlul_pkg::tl_h2d_t writer_tl_h_o_pre;
  tlul_cmd_intg_gen #(
  ) u_writer_cmd_intg_gen (
    .tl_i(writer_tl_h_o_pre),
    .tl_o(writer_tl_h_o)
  );


  // Reader will never write any data
  assign reader_tl_h_o_pre.a_user = '{
    default: '0,
    instr_type: prim_mubi_pkg::MuBi4False,
    data_intg: prim_secded_pkg::prim_secded_inv_39_32_enc('0)
  };

  assign writer_tl_h_o_pre.a_user = '{
    default: '0,
    instr_type: prim_mubi_pkg::MuBi4False,
    data_intg: '0
  };


  DMATop u_fastvdma (

    .clock                 (  clk_i                        ),
    .reset                 (  ~rst_ni                      ),

    // Control inputs
    .io_control_a_opcode   (  tl_d_i.a_opcode              ),
    .io_control_a_param    (  tl_d_i.a_param               ),
    .io_control_a_size     (  tl_d_i.a_size                ),
    .io_control_a_source   (  tl_d_i.a_source              ),
    .io_control_a_address  (  tl_d_i.a_address             ),
    .io_control_a_mask     (  tl_d_i.a_mask                ),
    .io_control_a_data     (  tl_d_i.a_data                ),
    .io_control_a_corrupt  (                               ),
    .io_control_a_valid    (  tl_d_i.a_valid               ),

    .io_control_a_ready    (  tl_d_o_pre.a_ready           ),

    // Control outputs
    .io_control_d_opcode   (  dma_control_d_opcode         ),
    .io_control_d_param    (  tl_d_o_pre.d_param           ),
    .io_control_d_size     (  tl_d_o_pre.d_size            ),
    .io_control_d_source   (  tl_d_o_pre.d_source          ),
    .io_control_d_sink     (  tl_d_o_pre.d_sink            ),
    .io_control_d_denied   (                               ),
    .io_control_d_data     (  tl_d_o_pre.d_data            ),
    .io_control_d_corrupt  (                               ),
    .io_control_d_valid    (  tl_d_o_pre.d_valid           ),

    .io_control_d_ready    (  tl_d_i.d_ready               ),


    // Reader outputs
    .io_read_a_opcode      (  dma_read_a_opcode            ),
    .io_read_a_param       (  reader_tl_h_o_pre.a_param    ),
    .io_read_a_size        (  reader_tl_h_o_pre.a_size     ),
    .io_read_a_source      (  reader_tl_h_o_pre.a_source   ),
    .io_read_a_address     (  reader_tl_h_o_pre.a_address  ),
    .io_read_a_mask        (  reader_tl_h_o_pre.a_mask     ),
    .io_read_a_data        (  reader_tl_h_o_pre.a_data     ),
    .io_read_a_corrupt     (                               ),
    .io_read_a_valid       (  reader_tl_h_o_pre.a_valid    ),

    .io_read_a_ready       (  reader_tl_h_i.a_ready        ),

    // Reader inputs
    .io_read_d_opcode      (  reader_tl_h_i.d_opcode       ),
    .io_read_d_param       (  reader_tl_h_i.d_param        ),
    .io_read_d_size        (  reader_tl_h_i.d_size         ),
    .io_read_d_source      (  reader_tl_h_i.d_source       ),
    .io_read_d_sink        (  reader_tl_h_i.d_sink         ),
    .io_read_d_denied      (                               ),
    .io_read_d_data        (  reader_tl_h_i.d_data         ),
    .io_read_d_corrupt     (                               ),
    .io_read_d_valid       (  reader_tl_h_i.d_valid        ),

    .io_read_d_ready       (  reader_tl_h_o_pre.d_ready    ),


    //// Writer outputs
    .io_write_a_opcode     (  dma_write_a_opcode           ),
    .io_write_a_param      (  writer_tl_h_o_pre.a_param    ),
    .io_write_a_size       (  writer_tl_h_o_pre.a_size     ),
    .io_write_a_source     (  writer_tl_h_o_pre.a_source   ),
    .io_write_a_address    (  writer_tl_h_o_pre.a_address  ),
    .io_write_a_mask       (  writer_tl_h_o_pre.a_mask     ),
    .io_write_a_data       (  writer_tl_h_o_pre.a_data     ),
    .io_write_a_corrupt    (                               ),
    .io_write_a_valid      (  writer_tl_h_o_pre.a_valid    ),

    .io_write_a_ready      (  writer_tl_h_i.a_ready        ),

    // Writer inputs
    .io_write_d_opcode     (  writer_tl_h_i.d_opcode       ),
    .io_write_d_param      (  writer_tl_h_i.d_param        ),
    .io_write_d_size       (  writer_tl_h_i.d_size         ),
    .io_write_d_source     (  writer_tl_h_i.d_source       ),
    .io_write_d_sink       (  writer_tl_h_i.d_sink         ),
    .io_write_d_denied     (                               ),
    .io_write_d_data       (  writer_tl_h_i.d_data         ),
    .io_write_d_corrupt    (                               ),
    .io_write_d_valid      (  writer_tl_h_i.d_valid        ),

    .io_write_d_ready      (  writer_tl_h_o_pre.d_ready    ),


    // Other signals
    .io_irq_readerDone     (  intr_reader_done_o           ),
    .io_irq_writerDone     (  intr_writer_done_o           ),
    .io_sync_readerSync    (  1'b0                         ),
    .io_sync_writerSync    (  1'b0                         )
  );

  // Explicitly throw controller error for comportability spec
  // if writes aren't addr aligned. The DMA IP truncates the
  // bottom two bits regardless.
  always_comb begin
    if (wr_req) begin
      addr_align_err = |tl_d_i.a_address[1:0];
    end else begin
      addr_align_err = 1'b0;
    end
  end

  assign meta_data_err = tl_a_user_chk(tl_d_i.a_user);

  tlul_err u_ctrl_err (
    .clk_i,
    .rst_ni,
    .tl_i (tl_d_i),
    .err_o (tl_err)
  );

endmodule
