Support for SystemVerilog interfaces as a port in the top level module + test case
authorRuben Undheim <ruben.undheim@gmail.com>
Sat, 20 Oct 2018 09:58:25 +0000 (11:58 +0200)
committerRuben Undheim <ruben.undheim@gmail.com>
Sat, 20 Oct 2018 09:58:25 +0000 (11:58 +0200)
frontends/ast/ast.cc
passes/hierarchy/hierarchy.cc
tests/svinterfaces/run-test.sh
tests/svinterfaces/runone.sh
tests/svinterfaces/svinterface_at_top.sv [new file with mode: 0644]
tests/svinterfaces/svinterface_at_top_ref.v [new file with mode: 0644]
tests/svinterfaces/svinterface_at_top_tb.v [new file with mode: 0644]
tests/svinterfaces/svinterface_at_top_tb_wrapper.v [new file with mode: 0644]
tests/svinterfaces/svinterface_at_top_wrapper.v [new file with mode: 0644]

index 1f2ecffde0c479a0b4aa631401574702464036d6..412e04f6e3d45a665cda26213aed9cc722e407ce 100644 (file)
@@ -904,7 +904,7 @@ RTLIL::Const AstNode::realAsConst(int width)
 }
 
 // create a new AstModule from an AST_MODULE AST node
-static AstModule* process_module(AstNode *ast, bool defer)
+static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL)
 {
        log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
 
@@ -920,7 +920,11 @@ static AstModule* process_module(AstNode *ast, bool defer)
        current_module->set_bool_attribute("\\cells_not_processed");
 
        current_ast_mod = ast;
-       AstNode *ast_before_simplify = ast->clone();
+       AstNode *ast_before_simplify;
+       if (original_ast != NULL)
+               ast_before_simplify = original_ast;
+       else
+               ast_before_simplify = ast->clone();
 
        if (flag_dump_ast1) {
                log("Dumping Verilog AST before simplification:\n");
@@ -1105,6 +1109,104 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
                }
        }
 
+       AstNode *ast_before_replacing_interface_ports = new_ast->clone();
+
+       // Explode all interface ports. Note this will only have any effect on top
+       // level modules. Other sub-modules will have their interface ports
+       // exploded in derive(..)
+       for (size_t i =0; i<new_ast->children.size(); i++)
+       {
+               AstNode *ch2 = new_ast->children[i];
+               std::string interface_type = "";
+               std::string interface_modport = "";
+               if (ch2->type == AST_INTERFACEPORT) {
+                       std::string name_port = ch2->str;
+                       if (ch2->children.size() > 0) {
+                               for(size_t j=0; j<ch2->children.size();j++) {
+                                       AstNode *ch = ch2->children[j];
+                                       if(ch->type == AST_INTERFACEPORTTYPE) {
+                                               std::string name_type = ch->str;
+                                               size_t ndots = std::count(name_type.begin(), name_type.end(), '.');
+                                               // Separate the interface instance name from any modports:
+                                               if (ndots == 0) { // Does not have modport
+                                                       interface_type = name_type;
+                                               }
+                                               else {
+                                                       std::stringstream name_type_stream(name_type);
+                                                       std::string segment;
+                                                       std::vector<std::string> seglist;
+                                                       while(std::getline(name_type_stream, segment, '.')) {
+                                                               seglist.push_back(segment);
+                                                       }
+                                                       if (ndots == 1) { // Has modport
+                                                               interface_type = seglist[0];
+                                                               interface_modport = seglist[1];
+                                                       }
+                                                       else { // Erroneous port type
+                                                               log_error("More than two '.' in signal port type (%s)\n", name_type.c_str());
+                                                       }
+                                               }
+                                               if (design->modules_.count(interface_type) > 0) {
+                                                       AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
+                                                       celltype_for_intf->str = interface_type;
+                                                       AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf);
+                                                       cell_for_intf->str = name_port + "_inst_from_top_dummy";
+                                                       new_ast->children.push_back(cell_for_intf);
+
+                                                       RTLIL::Module *intfmodule = design->modules_[interface_type];
+                                                       AstModule *ast_module_of_interface = (AstModule*)intfmodule;
+                                                       AstNode *ast_node_of_interface = ast_module_of_interface->ast;
+                                                       AstNode *modport = NULL;
+                                                       std::string interface_modport_compare_str = "\\" + interface_modport;
+                                                       for (auto &chm : ast_node_of_interface->children) {
+                                                               if (chm->type == AST_MODPORT) {
+                                                                       if (chm->str == interface_modport_compare_str) { // Modport found
+                                                                               modport = chm;
+                                                                       }
+                                                               }
+                                                       }
+
+                                                       std::string intfname = name_port;
+                                                       for (auto &wire_it : intfmodule->wires_){
+                                                               AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(wire_it.second->width -1, true), AstNode::mkconst_int(0, true)));
+                                                               std::string origname = log_id(wire_it.first);
+                                                               std::string newname = intfname + "." + origname;
+                                                               wire->str = newname;
+                                                               if (modport != NULL) {
+                                                                       bool found_in_modport = false;
+                                                                       // Search for the current wire in the wire list for the current modport
+                                                                       for (auto &ch : modport->children) {
+                                                                               if (ch->type == AST_MODPORTMEMBER) {
+                                                                                       std::string compare_name = "\\" + origname;
+                                                                                       if (ch->str == compare_name) { // Found signal. The modport decides whether it is input or output
+                                                                                               found_in_modport = true;
+                                                                                               wire->is_input = ch->is_input;
+                                                                                               wire->is_output = ch->is_output;
+                                                                                               break;
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                                       if (found_in_modport) {
+                                                                               new_ast->children.push_back(wire);
+                                                                       }
+                                                                       else { // If not found in modport, do not create port
+                                                                               delete wire;
+                                                                       }
+                                                               }
+                                                               else { // If no modport, set inout
+                                                                       wire->is_input = true;
+                                                                       wire->is_output = true;
+                                                                       new_ast->children.push_back(wire);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+
        // The old module will be deleted. Rename and mark for deletion:
        std::string original_name = this->name.str();
        std::string changed_name = original_name + "_before_replacing_local_interfaces";
@@ -1119,7 +1221,7 @@ void AstModule::reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RT
        }
 
        // Generate RTLIL from AST for the new module and add to the design:
-       AstModule *newmod = process_module(new_ast, false);
+       AstModule *newmod = process_module(new_ast, false, ast_before_replacing_interface_ports);
        delete(new_ast);
        design->add(newmod);
        RTLIL::Module* mod = design->module(original_name);
index 7e93a6f9af67671f1c875470801a3791a4e397e2..9c7dad3d33af2acd2ac4ce4ec7c577688f834b4a 100644 (file)
@@ -146,6 +146,17 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
        std::map<RTLIL::Cell*, std::pair<int, int>> array_cells;
        std::string filename;
 
+       bool has_interface_ports = false;
+
+       // If any of the ports are actually interface ports, we will always need to
+       // reprocess the module:
+       if(!module->get_bool_attribute("\\interfaces_replaced_in_module")) {
+               for (auto &wire : module->wires_) {
+                       if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface"))
+                               has_interface_ports = true;
+               }
+       }
+
        // Always keep track of all derived interfaces available in the current module in 'interfaces_in_module':
        dict<RTLIL::IdString, RTLIL::Module*> interfaces_in_module;
        for (auto &cell_it : module->cells_)
@@ -244,8 +255,14 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
                                        RTLIL::IdString interface_name = interface_name_str;
                                        bool not_found_interface = false;
                                        if(module->get_bool_attribute("\\interfaces_replaced_in_module")) { // If 'interfaces' in the cell have not be been handled yet, there is no need to derive the sub-module either
-                                               if (interfaces_in_module.count(interface_name) > 0) { // Check if the interface instance is present in module
-                                                       RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name);
+                                               int nexactmatch = interfaces_in_module.count(interface_name) > 0;
+                                               std::string interface_name_str2 =  interface_name_str + "_inst_from_top_dummy";
+                                               RTLIL::IdString interface_name2 = interface_name_str2;
+                                               int nmatch2 = interfaces_in_module.count(interface_name2) > 0;
+                                               if (nexactmatch > 0 || nmatch2 > 0) { // Check if the interface instance is present in module
+                                                       if (nexactmatch != 0)
+                                                               interface_name2 = interface_name;
+                                                       RTLIL::Module *mod_replace_ports = interfaces_in_module.at(interface_name2);
                                                        for (auto &mod_wire : mod_replace_ports->wires_) { // Go over all wires in interface, and add replacements to lists.
                                                                std::string signal_name1 = conn.first.str() + "." + log_id(mod_wire.first);
                                                                std::string signal_name2 = interface_name.str() + "." + log_id(mod_wire.first);
@@ -259,7 +276,7 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
                                                                }
                                                        }
                                                        connections_to_remove.push_back(conn.first);
-                                                       interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name);
+                                                       interfaces_to_add_to_submodule[conn.first] = interfaces_in_module.at(interface_name2);
 
                                                        // Add modports to a dict which will be passed to AstModule::derive
                                                        if (interface_modport != "") {
@@ -363,8 +380,8 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
        module->attributes.erase("\\cells_not_processed");
 
 
-       // If any interface instances were found in the module, we need to rederive it completely:
-       if (interfaces_in_module.size() > 0 && !module->get_bool_attribute("\\interfaces_replaced_in_module")) {
+       // If any interface instances or interface ports were found in the module, we need to rederive it completely:
+       if ((interfaces_in_module.size() > 0 || has_interface_ports) && !module->get_bool_attribute("\\interfaces_replaced_in_module")) {
                module->reprocess_module(design, interfaces_in_module);
                return did_something;
        }
@@ -438,6 +455,20 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
        for (auto &it : design->modules_)
                if (used.count(it.second) == 0)
                        del_modules.push_back(it.second);
+               else {
+                       // Now all interface ports must have been exploded, and it is hence
+                       // safe to delete all of the remaining dummy interface ports:
+                       pool<RTLIL::Wire*> del_wires;
+                       for(auto &wire : it.second->wires_) {
+                               if ((wire.second->port_input || wire.second->port_output) && wire.second->get_bool_attribute("\\is_interface")) {
+                                       del_wires.insert(wire.second);
+                               }
+                       }
+                       if (del_wires.size() > 0) {
+                               it.second->remove(del_wires);
+                               it.second->fixup_ports();
+                       }
+               }
 
        int del_counter = 0;
        for (auto mod : del_modules) {
index 1630859bd570a8a76defddf8b64f4842235eedb7..86567d1c1aa9f68207581037361e8208de1b18de 100755 (executable)
@@ -3,3 +3,4 @@
 
 
 ./runone.sh  svinterface1
+./runone.sh  svinterface_at_top
index 3458013892f43d214939b27a604770c15619f831..0adecc79779d1349dec8a7ccc2fc783222027bb0 100755 (executable)
@@ -22,11 +22,14 @@ iverilog -g2012 ${TESTNAME}_syn.v
 iverilog -g2012 ${TESTNAME}_ref_syn.v
 
 set +e
-
 iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_ref_syn.v
 ./a.out
 mv output.txt reference_result.txt
-iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v
+if [ -f ${TESTNAME}_wrapper.v ] ; then
+    iverilog -g2012 ${TESTNAME}_tb_wrapper.v ${TESTNAME}_syn.v
+else
+    iverilog -g2012 ${TESTNAME}_tb.v ${TESTNAME}_syn.v
+fi
 ./a.out
 mv output.txt dut_result.txt
 
diff --git a/tests/svinterfaces/svinterface_at_top.sv b/tests/svinterfaces/svinterface_at_top.sv
new file mode 100644 (file)
index 0000000..b5aa8c8
--- /dev/null
@@ -0,0 +1,125 @@
+
+
+module TopModule(
+    input logic clk,
+    input logic rst,
+    output logic [21:0] outOther,
+    input logic [1:0] sig,
+    input logic flip,
+    output logic [1:0] sig_out,
+    MyInterface.submodule1 interfaceInstanceAtTop,
+    output logic [15:0] passThrough);
+
+  MyInterface #(.WIDTH(4)) MyInterfaceInstance();
+
+  SubModule1 u_SubModule1 (
+    .clk(clk),
+    .rst(rst),
+    .u_MyInterface(MyInterfaceInstance),
+    .u_MyInterfaceFromTop(interfaceInstanceAtTop),
+    .outOther(outOther),
+    .sig (sig)
+  );
+
+  assign sig_out = MyInterfaceInstance.mysig_out;
+
+
+  assign MyInterfaceInstance.setting = flip;
+
+  assign passThrough = MyInterfaceInstance.passThrough;
+
+endmodule
+
+interface MyInterface #(
+  parameter WIDTH = 3)(
+  );
+
+  logic setting;
+  logic [WIDTH-1:0] other_setting;
+
+  logic [1:0] mysig_out;
+
+  logic [15:0] passThrough;
+
+    modport submodule1 (
+        input  setting,
+        output other_setting,
+        output mysig_out,
+        output passThrough
+    );
+
+    modport submodule2 (
+        input  setting,
+        output other_setting,
+        input  mysig_out,
+        output passThrough
+    );
+
+endinterface
+
+
+module SubModule1(
+    input logic clk,
+    input logic rst,
+    MyInterface.submodule1 u_MyInterface,
+    MyInterface.submodule1 u_MyInterfaceFromTop,
+    input logic [1:0] sig,
+    output logic [21:0] outOther
+
+  );
+
+
+  always_ff @(posedge clk or posedge rst)
+    if(rst)
+      u_MyInterface.mysig_out <= 0;
+    else begin
+      if(u_MyInterface.setting)
+        u_MyInterface.mysig_out <= sig;
+      else
+        u_MyInterface.mysig_out <= ~sig;
+    end
+
+  MyInterface #(.WIDTH(22)) MyInterfaceInstanceInSub();
+
+  SubModule2 u_SubModule2 (
+    .clk(clk),
+    .rst(rst),
+    .u_MyInterfaceFromTopDown(u_MyInterfaceFromTop),
+    .u_MyInterfaceInSub2(u_MyInterface),
+    .u_MyInterfaceInSub3(MyInterfaceInstanceInSub)
+  );
+
+    assign outOther = MyInterfaceInstanceInSub.other_setting;
+
+    assign MyInterfaceInstanceInSub.setting = 0;
+    assign MyInterfaceInstanceInSub.mysig_out = sig;
+
+endmodule
+
+module SubModule2(
+
+    input logic clk,
+    input logic rst,
+    MyInterface.submodule2 u_MyInterfaceInSub2,
+    MyInterface.submodule1 u_MyInterfaceFromTopDown,
+    MyInterface.submodule2 u_MyInterfaceInSub3
+
+  );
+
+  assign u_MyInterfaceFromTopDown.mysig_out = u_MyInterfaceFromTop.setting ? 10 :  20;
+
+   always_comb begin
+      if (u_MyInterfaceInSub3.mysig_out == 2'b00)
+        u_MyInterfaceInSub3.other_setting[21:0] = 1000;
+      else if (u_MyInterfaceInSub3.mysig_out == 2'b01)
+        u_MyInterfaceInSub3.other_setting[21:0] = 2000;
+      else if (u_MyInterfaceInSub3.mysig_out == 2'b10)
+        u_MyInterfaceInSub3.other_setting[21:0] = 3000;
+      else
+        u_MyInterfaceInSub3.other_setting[21:0] = 4000;
+   end
+
+    assign u_MyInterfaceInSub2.passThrough[7:0] = 124;
+    assign u_MyInterfaceInSub2.passThrough[15:8] = 200;
+
+endmodule
diff --git a/tests/svinterfaces/svinterface_at_top_ref.v b/tests/svinterfaces/svinterface_at_top_ref.v
new file mode 100644 (file)
index 0000000..7b54a26
--- /dev/null
@@ -0,0 +1,120 @@
+
+module TopModule(
+    input logic clk,
+    input logic rst,
+    input logic [1:0] sig,
+    input logic flip,
+    output logic [15:0] passThrough,
+    output logic [21:0] outOther,
+    input logic interfaceInstanceAtTop_setting,
+    output logic [2:0] interfaceInstanceAtTop_other_setting,
+    output logic [1:0] interfaceInstanceAtTop_mysig_out,
+    output logic [15:0] interfaceInstanceAtTop_passThrough,
+    output logic [1:0] sig_out);
+
+
+    logic MyInterfaceInstance_setting;
+    logic [3:0] MyInterfaceInstance_other_setting;
+    logic [1:0] MyInterfaceInstance_mysig_out;
+
+  SubModule1 u_SubModule1 (
+    .clk(clk),
+    .rst(rst),
+    .u_MyInterface_setting(MyInterfaceInstance_setting),
+    .u_MyInterface_mysig_out(MyInterfaceInstance_mysig_out),
+    .u_MyInterface_other_setting(MyInterfaceInstance_other_setting),
+    .u_MyInterfaceFromTop_setting(interfaceInstanceAtTop_setting),
+    .u_MyInterfaceFromTop_other_setting(interfaceInstanceAtTop_other_setting),
+    .u_MyInterfaceFromTop_mysig_out(interfaceInstanceAtTop_mysig_out),
+    .u_MyInterfaceFromTop_passThrough(interfaceInstanceAtTop_passThrough),
+    .outOther(outOther),
+    .passThrough (passThrough),
+    .sig (sig)
+  );
+
+  assign sig_out = MyInterfaceInstance_mysig_out;
+
+
+  assign MyInterfaceInstance_setting = flip;
+
+endmodule
+
+
+module SubModule1(
+    input logic clk,
+    input logic rst,
+    input logic u_MyInterface_setting,
+    output logic [3:0] u_MyInterface_other_setting,
+    output logic [1:0] u_MyInterface_mysig_out,
+    output logic [21:0] outOther,
+    input logic [1:0] sig,
+    input logic u_MyInterfaceFromTop_setting,
+    output logic [2:0]  u_MyInterfaceFromTop_other_setting,
+    output logic [1:0]  u_MyInterfaceFromTop_mysig_out,
+    output logic [14:0] u_MyInterfaceFromTop_passThrough,
+    output logic [15:0] passThrough
+  );
+
+  always @(posedge clk or posedge rst)
+    if(rst)
+      u_MyInterface_mysig_out <= 0;
+    else begin
+      if(u_MyInterface_setting)
+        u_MyInterface_mysig_out <= sig;
+      else
+        u_MyInterface_mysig_out <= ~sig;
+    end
+
+    logic MyInterfaceInstanceInSub_setting;
+    logic [21:0] MyInterfaceInstanceInSub_other_setting;
+    logic [1:0] MyInterfaceInstanceInSub_mysig_out;
+
+  assign u_MyInterfaceFromTop_mysig_out = u_MyInterfaceFromTop_setting ? 10 :  20;
+
+  SubModule2 u_SubModule2 (
+    .clk(clk),
+    .rst(rst),
+    .u_MyInterfaceInSub2_setting(u_MyInterface_setting),
+    .u_MyInterfaceInSub2_mysig_out(u_MyInterface_mysig_out),
+    .u_MyInterfaceInSub2_other_setting(u_MyInterface_other_setting),
+    .u_MyInterfaceInSub3_setting(MyInterfaceInstanceInSub_setting),
+    .u_MyInterfaceInSub3_mysig_out(MyInterfaceInstanceInSub_mysig_out),
+    .u_MyInterfaceInSub3_other_setting(MyInterfaceInstanceInSub_other_setting),
+    .passThrough (passThrough)
+  );
+    assign outOther = MyInterfaceInstanceInSub_other_setting;
+
+    assign MyInterfaceInstanceInSub_setting = 0;
+    assign MyInterfaceInstanceInSub_mysig_out = sig;
+
+endmodule
+
+module SubModule2(
+
+    input logic clk,
+    input logic rst,
+    input logic u_MyInterfaceInSub2_setting,
+    output logic [3:0] u_MyInterfaceInSub2_other_setting,
+    input  logic [1:0] u_MyInterfaceInSub2_mysig_out,
+    input logic u_MyInterfaceInSub3_setting,
+    output logic [21:0] u_MyInterfaceInSub3_other_setting,
+    input  logic [1:0] u_MyInterfaceInSub3_mysig_out,
+    output logic [15:0] passThrough
+
+  );
+
+    always @(u_MyInterfaceInSub3_mysig_out) begin
+      if (u_MyInterfaceInSub3_mysig_out == 2'b00)
+        u_MyInterfaceInSub3_other_setting[21:0] = 1000;
+      else if (u_MyInterfaceInSub3_mysig_out == 2'b01)
+        u_MyInterfaceInSub3_other_setting[21:0] = 2000;
+      else if (u_MyInterfaceInSub3_mysig_out == 2'b10)
+        u_MyInterfaceInSub3_other_setting[21:0] = 3000;
+      else
+        u_MyInterfaceInSub3_other_setting[21:0] = 4000;
+    end
+
+    assign passThrough[7:0] = 124;
+    assign passThrough[15:8] = 200;
+
+endmodule
diff --git a/tests/svinterfaces/svinterface_at_top_tb.v b/tests/svinterfaces/svinterface_at_top_tb.v
new file mode 100644 (file)
index 0000000..bf37a14
--- /dev/null
@@ -0,0 +1,68 @@
+`timescale 1ns/10ps
+
+module svinterface_at_top_tb;
+
+
+  logic clk;
+  logic rst;
+  logic [21:0] outOther;
+  logic [1:0] sig;
+  logic [1:0] sig_out;
+  logic flip;
+  logic [15:0] passThrough;
+  integer outfile;
+
+  logic interfaceInstanceAtTop_setting;
+  logic [2:0] interfaceInstanceAtTop_other_setting;
+  logic [1:0] interfaceInstanceAtTop_mysig_out;
+  logic [15:0] interfaceInstanceAtTop_passThrough;
+
+
+  TopModule u_dut (
+    .clk(clk),
+    .rst(rst),
+    .outOther(outOther),
+    .sig(sig),
+    .flip(flip),
+    .passThrough(passThrough),
+    .interfaceInstanceAtTop_setting(interfaceInstanceAtTop_setting),
+    .interfaceInstanceAtTop_other_setting(interfaceInstanceAtTop_other_setting),
+    .interfaceInstanceAtTop_mysig_out(interfaceInstanceAtTop_mysig_out),
+    .interfaceInstanceAtTop_passThrough(interfaceInstanceAtTop_passThrough),
+    .sig_out(sig_out)
+  );
+
+  initial begin
+    clk = 0;
+    while(1) begin
+      clk = ~clk;
+      #50;
+    end
+  end
+
+  initial begin
+    outfile = $fopen("output.txt");
+    rst = 1;
+    interfaceInstanceAtTop_setting = 0;
+    sig = 0;
+    flip = 0;
+    @(posedge clk);
+    #(2);
+    rst = 0;
+    @(posedge clk);
+    for(int j=0;j<2;j++) begin
+      for(int i=0;i<20;i++) begin
+        #(2);
+        flip = j;
+        sig = i;
+        @(posedge clk);
+      end
+    end
+    $finish;
+  end
+
+  always @(negedge clk) begin
+    $fdisplay(outfile, "%d %d %d %d", outOther, sig_out, passThrough, interfaceInstanceAtTop_mysig_out);
+  end
+
+endmodule
diff --git a/tests/svinterfaces/svinterface_at_top_tb_wrapper.v b/tests/svinterfaces/svinterface_at_top_tb_wrapper.v
new file mode 100644 (file)
index 0000000..b344a7b
--- /dev/null
@@ -0,0 +1,68 @@
+`timescale 1ns/10ps
+
+module svinterface_at_top_tb_wrapper;
+
+
+  logic clk;
+  logic rst;
+  logic [21:0] outOther;
+  logic [1:0] sig;
+  logic [1:0] sig_out;
+  logic flip;
+  logic [15:0] passThrough;
+  integer outfile;
+
+  logic interfaceInstanceAtTop_setting;
+  logic [2:0] interfaceInstanceAtTop_other_setting;
+  logic [1:0] interfaceInstanceAtTop_mysig_out;
+  logic [15:0] interfaceInstanceAtTop_passThrough;
+
+
+  TopModule u_dut (
+    .clk(clk),
+    .rst(rst),
+    .outOther(outOther),
+    .sig(sig),
+    .flip(flip),
+    .passThrough(passThrough),
+    .\interfaceInstanceAtTop.setting (interfaceInstanceAtTop_setting),
+    .\interfaceInstanceAtTop.other_setting (interfaceInstanceAtTop_other_setting),
+    .\interfaceInstanceAtTop.mysig_out (interfaceInstanceAtTop_mysig_out),
+    .\interfaceInstanceAtTop.passThrough (interfaceInstanceAtTop_passThrough),
+    .sig_out(sig_out)
+  );
+
+  initial begin
+    clk = 0;
+    while(1) begin
+      clk = ~clk;
+      #50;
+    end
+  end
+
+  initial begin
+    outfile = $fopen("output.txt");
+    rst = 1;
+    sig = 0;
+    interfaceInstanceAtTop_setting = 0;
+    flip = 0;
+    @(posedge clk);
+    #(2);
+    rst = 0;
+    @(posedge clk);
+    for(int j=0;j<2;j++) begin
+      for(int i=0;i<20;i++) begin
+        #(2);
+        flip = j;
+        sig = i;
+        @(posedge clk);
+      end
+    end
+    $finish;
+  end
+
+  always @(negedge clk) begin
+    $fdisplay(outfile, "%d %d %d %d", outOther, sig_out, passThrough, interfaceInstanceAtTop_mysig_out);
+  end
+
+endmodule
diff --git a/tests/svinterfaces/svinterface_at_top_wrapper.v b/tests/svinterfaces/svinterface_at_top_wrapper.v
new file mode 100644 (file)
index 0000000..64f906c
--- /dev/null
@@ -0,0 +1,33 @@
+`timescale 1ns/10ps
+
+module svinterface_at_top_wrapper(
+  input logic clk,
+  input logic rst,
+  output logic [21:0] outOther,
+  input logic [1:0] sig,
+  output logic [1:0] sig_out,
+  input logic flip,
+  output logic [15:0] passThrough,
+
+    input logic interfaceInstanceAtTop_setting,
+    output logic [2:0] interfaceInstanceAtTop_other_setting,
+    output logic [1:0] interfaceInstanceAtTop_mysig_out,
+    output logic [15:0] interfaceInstanceAtTop_passThrough,
+  );
+
+
+  TopModule u_dut (
+    .clk(clk),
+    .rst(rst),
+    .outOther(outOther),
+    .sig(sig),
+    .flip(flip),
+    .passThrough(passThrough),
+    .\interfaceInstanceAtTop.setting(interfaceInstanceAtTop_setting),
+    .\interfaceInstanceAtTop.other_setting(interfaceInstanceAtTop_other_setting),
+    .\interfaceInstanceAtTop.mysig_out(interfaceInstanceAtTop_mysig_out),
+    .\interfaceInstanceAtTop.passThrough(interfaceInstanceAtTop_passThrough),
+    .sig_out(sig_out)
+  );
+
+endmodule