// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//

module tb;

  import uvm_pkg::*;
  import rjtag_pkg::*;

  localparam int NrHarts = 1;
  localparam int ClkPeriod = 10; // 10ns

  logic clk;
  logic rst_n;
  logic ndmrst;
  logic dmactive;
  logic [NrHarts-1:0] debug_req;
  logic [NrHarts-1:0] unavailable;

  xbar_if tlul_mem_if(clk);
  xbar_if tlul_dm_if(clk);

  // clk & reset
  initial begin
    clk = 1'b0;
    forever begin
      #(ClkPeriod/2) clk=~clk;
    end
  end

  initial begin
    rst_n = 1'b0;
    repeat(3) @(negedge clk);
    rst_n = 1'b1;
  end

  initial begin
    #100us
    $finish(1);
  end

  logic clk_jtag, rst_jtag_n;

  jtag_if jtag();

  initial begin
    uvm_config_db#(virtual jtag_if)::set(null,"*","vif", jtag);
  end

  initial begin
    run_test();
  end


  dm::dmi_req_t  dmi_req;
  dm::dmi_resp_t dmi_rsp;

  // Device SRAM:
  device_sram sram;
  initial begin
    sram = new(0);
    sram.connect(tlul_dm_if.device);

    sram.run();
  end

  rv_dm #(
    .NrHarts      (NrHarts),
    .AxiIdWidth   (  8),
    .AxiAddrWidth ( 32),
    .AxiDataWidth ( 32),
    .AxiUserWidth ( 16)
  ) u_dm_top (
    .clk_i         (clk),         // in clock
    .rst_ni        (rst_n),       // in asynchronous reset active low, connect PoR here, not the system reset
    .testmode_i    (1'b0),        // in
    .ndmreset_o    (ndmrst),      // out               non-debug module reset
    .dmactive_o    (dmactive),    // out               debug module is active
    .debug_req_o   (debug_req),   // out [NrHarts-1:0] async debug request
    .unavailable_i (unavailable), // in  [NrHarts-1:0] communicate whether the hart is unavailable (e.g.: power down)

    // bus device, for an execution based technique
    //.tl_d_i        (tlul_mem_if.device.h2d),
    //.tl_d_o        (tlul_mem_if.host.h2d),

    // bus host, for system bus accesses
    .tl_h_o        (tlul_dm_if.host.h2d),
    .tl_h_i        (tlul_dm_if.host.d2h),

    // Connection to DTM - compatible to RocketChip Debug Module
    .dmi_rst_ni       (dmi_rst_n),
    .dmi_req_valid_i  (dmi_req_valid),
    .dmi_req_ready_o  (dmi_req_ready),
    .dmi_req_i        (dmi_req      ),

    .dmi_resp_valid_o (dmi_rsp_valid),
    .dmi_resp_ready_i (dmi_rsp_ready),
    .dmi_resp_o       (dmi_rsp      )
  );

  dmi_jtag dap (
    .clk_i            (clk),
    .rst_ni           (rst_n),
    .testmode_i       (1'b0),

    .dmi_rst_no       (dmi_rst_n),
    .dmi_req_o        (dmi_req),
    .dmi_req_valid_o  (dmi_req_valid),
    .dmi_req_ready_i  (dmi_req_ready),

    .dmi_resp_i       (dmi_rsp      ),
    .dmi_resp_ready_o (dmi_rsp_ready),
    .dmi_resp_valid_i (dmi_rsp_valid),

    //JTAG
    .tck_i            (jtag.dut.tck   ),
    .tms_i            (jtag.dut.tms   ),
    .trst_ni          (jtag.dut.trst_n),
    .td_i             (jtag.dut.tdi   ),
    .td_o             (jtag.dut.tdo   ),
    .tdo_oe_o         (jtag.dut.tdo_oe)
  );

  localparam JTCK_PERIOD = 27.3ns;
  initial begin
    jtag.tb.tck = 0;
    forever begin
      #(JTCK_PERIOD/2) jtag.tb.tck = ~jtag.tb.tck;
    end
  end
  initial begin
    jtag.tb.trst_n = 1'b0;
    #50ns;
    jtag.tb.trst_n = 1'b1;
  end

endmodule
