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

// tb__xbar_connect generated by `topgen.py` tool

// This file must be `included in `hw/top_<toplevel>/dv/tb/tb.sv.
<%
from collections import OrderedDict
import topgen.lib as lib

top_hier = 'tb.dut.top_' + top["name"] + '.'
clk_hier = top_hier + top["clocks"].hier_paths["top"]

clk_src = OrderedDict()
for xbar in top["xbar"]:
  for clk, src in xbar["clock_srcs"].items():
    clk_src[clk] = src

clk_freq = OrderedDict()
for clock in top["clocks"].all_srcs.values():
  if clock.name in clk_src.values():
    clk_freq[clock.name] = clock.freq

hosts = OrderedDict()
devices = OrderedDict()
for xbar in top["xbar"]:
  for node in xbar["nodes"]:
    if node["type"] == "host" and not node["xbar"]:
      hosts[node["name"]] = "clk_" + clk_src[node["clock"]]
    elif node["type"] == "device" and not node["xbar"]:
      devices[node["name"]] = "clk_" + clk_src[node["clock"]]

def escape_if_name(qual_if_name):
    return qual_if_name.replace('.', '__')

%>\

## Need to use a variable assignment for "\" to bypass the newline filter.
`define DRIVE_CHIP_TL_HOST_IF(tl_name, inst_name, sig_name) ${"\\"}
     force ``tl_name``_tl_if.d2h = dut.top_${top["name"]}.u_``inst_name``.``sig_name``_i; ${"\\"}
     force dut.top_${top["name"]}.u_``inst_name``.``sig_name``_o = ``tl_name``_tl_if.h2d; ${"\\"}
     force dut.top_${top["name"]}.u_``inst_name``.clk_i = 0; ${"\\"}
     uvm_config_db#(virtual tl_if)::set(null, $sformatf("*env.%0s_agent", `"tl_name`"), "vif", ${"\\"}
                                        ``tl_name``_tl_if);

`define DRIVE_CHIP_TL_DEVICE_IF(tl_name, inst_name, sig_name) ${"\\"}
     force ``tl_name``_tl_if.h2d = dut.top_${top["name"]}.u_``inst_name``.``sig_name``_i; ${"\\"}
     force dut.top_${top["name"]}.u_``inst_name``.``sig_name``_o = ``tl_name``_tl_if.d2h; ${"\\"}
     force dut.top_${top["name"]}.u_``inst_name``.clk_i = 0; ${"\\"}
     uvm_config_db#(virtual tl_if)::set(null, $sformatf("*env.%0s_agent", `"tl_name`"), "vif", ${"\\"}
                                        ``tl_name``_tl_if);

`define DRIVE_CHIP_TL_EXT_DEVICE_IF(tl_name, inst_name, port_name) ${"\\"}
     force ``tl_name``_tl_if.h2d = dut.u_``inst_name``.``port_name``_i; ${"\\"}
     force dut.u_``inst_name``.``port_name``_o = ``tl_name``_tl_if.d2h; ${"\\"}
     uvm_config_db#(virtual tl_if)::set(null, $sformatf("*env.%0s_agent", `"tl_name`"), "vif", ${"\\"}
                                        ``tl_name``_tl_if);

% for c in clk_freq.keys():
wire clk_${c};
clk_rst_if clk_rst_if_${c}(.clk(clk_${c}), .rst_n(rst_n));
% endfor

% for i, clk in hosts.items():
tl_if ${escape_if_name(i)}_tl_if(${clk}, rst_n);
% endfor

% for i, clk in devices.items():
tl_if ${escape_if_name(i)}_tl_if(${clk}, rst_n);
% endfor

initial begin
  wait (xbar_mode !== 1'bx);
  if (xbar_mode) begin
    // only enable assertions in xbar as many pins are unconnected
    $assertoff(0, tb);
% for xbar in top["xbar"]:
    $asserton(0, tb.dut.top_${top["name"]}.u_xbar_${xbar["name"]});
% endfor

% for c in clk_freq.keys():
    clk_rst_if_${c}.set_active(.drive_rst_n_val(0));
    clk_rst_if_${c}.set_freq_khz(${clk_freq[c]} / 1000);
% endfor

    // bypass clkmgr, force clocks directly
% for xbar in top["xbar"]:
  % for clk, src in xbar["clock_srcs"].items():
    force ${top_hier}u_xbar_${xbar["name"]}.${clk} = clk_${src};
  % endfor
% endfor

    // bypass rstmgr, force resets directly
% for xbar in top["xbar"]:
  % for rst in xbar["reset_connections"]:
    force ${top_hier}u_xbar_${xbar["name"]}.${rst} = rst_n;
  % endfor
% endfor

% for xbar in top["xbar"]:
  % for node in xbar["nodes"]:
<%
clk = 'clk_' + clk_src[node["clock"]]
esc_name = node['name'].replace('.', '__')
inst_sig_list = lib.find_otherside_modules(top, xbar["name"], 'tl_' + esc_name)
inst_name = inst_sig_list[0][1]
sig_name = inst_sig_list[0][2]

# Handle the special cases of instance and signal names
if esc_name == "tlul_mailbox_sec":
  sig_name = "core0_tl"
elif esc_name == "tlul_mailbox_smc":
  inst_name = "tlul_mailbox_sec"
  sig_name = "core1_tl"
elif esc_name =="ram_smc":
  inst_name = "tl_adapter_ram_smc"
%>\
    % if node["type"] == "host" and not node["xbar"]:
    `DRIVE_CHIP_TL_HOST_IF(${esc_name}, ${inst_name}, ${sig_name})
    % elif node["type"] == "device" and not node["xbar"] and node["stub"]:
    `DRIVE_CHIP_TL_EXT_DEVICE_IF(${esc_name}, ${inst_name}, ${sig_name})
    % elif node["type"] == "device" and not node["xbar"]:
    `DRIVE_CHIP_TL_DEVICE_IF(${esc_name}, ${inst_name}, ${sig_name})
    % endif
  % endfor
% endfor
  end
end

`undef DRIVE_CHIP_TL_HOST_IF
`undef DRIVE_CHIP_TL_DEVICE_IF
`undef DRIVE_CHIP_TL_EXT_DEVICE_IF
