Verilog/C++: How to use IsUserDeclared() : Example for port associations

From Verific Design Automation FAQ
Jump to: navigation, search

Verific objects that are derived from DesignObj can be checked for Linefile information using IsUserDeclared(). If the derived object, such as a port, instance, or netlist contains Linefile information, IsUserDeclared() will return 1, otherwise it will return 0. Linefile information is stored for all objects read from HDL source files, so IsUserDeclared() can be used to check whether an instance was created as a result of the HDL input, versus being an operator or primitive that was created by Verific.

When a design has already passed RTL elaboration, any objects that are added to it are, by default, NOT user-declared. In situations where it may be necessary to make these objects user-declared, simply providing Linefile information for the object will do the job. One example where this may be desired is when we write out a Verilog netlist after making design modifications. Any object added without Linefile data will not be considered user-declared, and because Verific writes non-user-declared instances using implicit port-ordering syntax, thsee objects will be written out as such. However Verific writes out the other design objects that were derived from HDL using explicit named-association syntax. By adding Linefile information to these new objects added after RTL elaboration, the resulting netlist will have a consistent naming convention for all instantiations.

One way to add Linefile() information to an object is during its creation. Adding to a new netlist can be done as follows :

       Netlist *newNetlist2 = newCell2->Add(new Netlist("mymod2", top->Linefile())) ;

and adding to a port :

       newNetlist2->Add(new Port("out", DIR_OUT, top->Linefile())) ;

Please see below for a complete example on how IsUserDeclared() is used.

C++:

#include <iostream>
#include "Map.h"         // Make associated hash table class Map available
#include "Message.h"     // Make message handlers available
#include "veri_file.h"   // Make verilog reader available
#include "VeriWrite.h"   // Make verilog writer available
#include "DataBase.h"    // Make (hierarchical netlist) database API available
#include "Strings.h"     // Definition of class to manipulate copy, concatenate, create etc...

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

int main(int argc, char **argv)
{
    // Analyze and elaborate the design
    if (!veri_file::Read("top.v","work", veri_file::VERILOG_2K /*v2k*/)) return 1 ;

    // Get a handle to the top-level netlist
    Netlist *top = Netlist::PresentDesign() ;
    if (!top) {
        Message::PrintLine("Cannot find any handle to the top-level netlist") ;
        return 3 ;
    }

    // Print name of the top level module
    Message::Msg(VERIFIC_INFO, 0, top->Linefile(), "top level design is %s(%s)",
                 top->Owner()->Name(), top->Name()) ;

    // Add two more ports to the top level module
    // Port "c" is added without Linefile info, port "d" has Linefile borrowed from module "top"
    Port *port_c, *port_d ;
    port_c = top->Add(new Port("c", DIR_OUT)) ;
    port_d = top->Add(new Port("d", DIR_OUT, top->Linefile())) ;

    // Add two nets to connect to the two ports "c" and "d"
    Net *net_c = top->Add(new Net("c")) ;
    if (net_c && port_c)
        net_c->Connect(port_c) ;

    Net *net_d = top->Add(new Net("d")) ;
    if (net_d && port_d)
        net_d->Connect(port_d) ;

/****************
 * Create inst1
 * **************/

    // Create a new module mymod1
    // Note that we are not specifying any Linefile information here, so we expect this to NOT be user-declared
    // Verific will treat this instance as if it were a primitive/operator and write it out using ordered-port association
    Cell *newCell1 = new Cell("mymod1") ;
    Netlist *newNetlist1 = newCell1->Add(new Netlist("mymod1")) ;
    newNetlist1->Add(new Port("out", DIR_OUT)) ;
    newNetlist1->Add(new Port("in", DIR_IN)) ;

    // Now create and add an instance my_inst1 of modue mymod1
    Instance *inst = top->Add(new Instance("my_inst1", newNetlist1)) ;

    // Find the port on Netlist "mymod1" :
    Port *port = newNetlist1->GetPort("out") ;

    // And now connect the nets to the ports of my_inst1
    if (port)
        net_c->Connect(inst, port) ;

    Net *net_a = top->GetNet("a") ;
    port = newNetlist1->GetPort("in") ;
    if (port)
        net_a->Connect(inst, port) ;

    // Check if my_inst1 is user-declared. Note in the output log that it is not.
    if (inst->View()->IsUserDeclared())
        Message::Msg(VERIFIC_INFO, 0, inst->Linefile(), "Instance %s is user declared -- writing named connections", inst->Name()) ;
    else
        Message::Msg(VERIFIC_INFO, 0, inst->Linefile(), "Instance %s is not user declared -- writing ordered connections", inst->Name()) ;

/****************
 * Create inst2
 * **************/

    // Create a new module mymod2
    // Here we will call the constructor with Linefile information from the top-level netlist
    // As long as there is valid Linefile data, Verific considers it to be user-declared
    // Verific will write out user-declared instances using explicit named-port association
    Cell *newCell2 = new Cell("mymod2") ;
    Netlist *newNetlist2 = newCell2->Add(new Netlist("mymod2", top->Linefile())) ;
    newNetlist2->Add(new Port("out", DIR_OUT)) ;
    newNetlist2->Add(new Port("in1", DIR_IN)) ;
    newNetlist2->Add(new Port("in2", DIR_IN)) ;

    // Now create and add an instance my_inst2 of module mymod2
    inst = top->Add(new Instance("my_inst2", newNetlist2, top->Linefile()));

    // Find the port on Netlist "mymod2" :
    port = newNetlist2->GetPort("out") ;

    // And now connect the nets to the ports of my_inst2
    if (port)
        net_d->Connect(inst, port) ;

    port = newNetlist2->GetPort("in1") ;
    if (port) net_a->Connect(inst, port) ;

    port = newNetlist2->GetPort("in2") ;
    Net *net_b = top->GetNet("b") ;
    if (port)
        net_b->Connect(inst, port) ;

    // Check if my_inst2 is user-declared. Note in that having the Linefile info makes it user-declared, as shown in the output log
    if (inst->View()->IsUserDeclared())
        Message::Msg(VERIFIC_INFO, 0, inst->Linefile(), "Instance %s is user declared -- writing named connections", inst->Name()) ;
    else
        Message::Msg(VERIFIC_INFO, 0, inst->Linefile(), "Instance %s is not user declared -- writing ordered connections", inst->Name()) ;

    // Check whether the ports of the top-level are user-declared or not
    // Ports "c" should not be user-declared, but port "d" has Linefile info added, so it is user-declared
    MapIter mi ;
    FOREACH_PORT_OF_NETLIST(top, mi, port) {
        if (port->IsUserDeclared())
            Message::Msg(VERIFIC_INFO, 0, port->Linefile(), "port %s is user declared", port->Name()) ;
        else
            Message::Msg(VERIFIC_INFO, 0, port->Linefile(), "port %s is not user declared -- no Linefile information is available", port->Name()) ;

    }

    // Write out the netlist to show the newly added instance
    VeriWrite veriWriter ;
    veriWriter.WriteFile("Output_netlist.v", top) ;

    return 0 ;
}
 

top.v

module TOP(a,b,out);
    input a,b;
    output out;

    AND i1(a,b,out);
endmodule

module AND (inp1, inp2, out);
    input inp1,inp2;
    output out;
    assign out = inp1 & inp2;
endmodule
 

Output_netlist.v

//
// Verific Verilog Description of module TOP
//

module TOP (a, b, out, c, d);   // top.v(1)
    input a;   // top.v(2)
    input b;   // top.v(2)
    output out;   // top.v(3)
    output c;
    output d;   // top.v(1)


    mymod2 my_inst2 (.out(d), .in1(a), .in2(b));   // top.v(1)
    mymod1 my_inst1 (c, a);
    AND i1 (.inp1(a), .inp2(b), .out(out));   // top.v(5)

endmodule

//
// Verific Verilog Description of module mymod2
// module not written out since it is a black box. 
//


//
// Verific Verilog Description of module mymod1
// module not written out since it is a black box. 
//


//
// Verific Verilog Description of module AND
//

module AND (inp1, inp2, out);   // top.v(8)
    input inp1;   // top.v(9)
    input inp2;   // top.v(9)
    output out;   // top.v(10)


    and (out, inp1, inp2) ;   // top.v(11)

endmodule