Type Range example with multi-dimensional arrays

From Verific Design Automation FAQ
Jump to: navigation, search

For a design with multidimensional arrays, the application needs to create a data structure for mapping NetBus to TypeRange.

C++:

#include <iostream>
#include "veri_file.h"
#include "DataBase.h"
#include "Map.h"

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

void CreateTypeRangeMapping(const Netlist *nl, Map &net_bus_vs_tr)
{
    if (!nl) return ;

    // Get the Verilog id name vs Set of Net or NetBus created.
    // Runtime flag 'db_add_id_vs_netbus_map' needs to be set while elaborating the design:
    const Map *id_vs_nets = nl->GetIdNetsTable() ;

    const Map *id_vs_tr = nl->GetTypeRangeTable() ; // Get the Verilog id name vs its TypeRange
    if (!id_vs_tr) return ;

    MapIter mi ;
    const char *id_name ;
    const Set *net_or_netbus ;
    const TypeRange *tr ;
    FOREACH_MAP_ITEM(id_vs_nets, mi, &id_name, &net_or_netbus) {
        tr = (TypeRange *)id_vs_tr->GetValue(id_name) ;
        if (!tr) continue ;
        SetIter si ;
        DesignObj *obj ;
        FOREACH_SET_ITEM(net_or_netbus, si, &obj) {
            // Only insert for NetBusses, we do not need Nets:
            if (obj->IsNetBus()) (void) net_bus_vs_tr.Insert(obj, tr) ;
        }
    }
}

int main(int argc, const char **argv)
{
    RuntimeFlags::SetVar("db_preserve_user_nets", 1) ;
    RuntimeFlags::SetVar("db_add_id_vs_netbus_map", 1) ;
    if (!veri_file::Read("test.v", "work", veri_file::SYSTEM_VERILOG)) return 1 ;

    Netlist *netlist = Netlist::PresentDesign() ;

    Map net_bus_vs_tr(POINTER_HASH) ;
    CreateTypeRangeMapping(netlist, net_bus_vs_tr) ;

    MapIter mi ;
    Net *net ;
    const TypeRange *tr ;
    FOREACH_NET_OF_NETLIST(netlist, mi, net) {
        if (!net || (net->IsUserDeclared() == 0)) {
             continue;
        }
        if (net->Bus()) {
            const char *name = net->Bus()->Name();
            tr = (const TypeRange *)net_bus_vs_tr.GetValue(net->Bus()) ;
            if (!tr) continue ; // Something wrong happened

            // Find if it has unpacked and/or packed dimensions: if it is unpacked, it must be the last dimension:
            unsigned has_unpacked_dim = (tr->IsTypeArray() && tr->IsPackedDimensionRange()) ? 0 : 1 ;
            // Packed dimensions may be there after the unpacked dimensions, find if there:
            unsigned has_packed_dim = (tr->IsTypeArray() && tr->IsPackedDimensionRange()) ? 1 : 0 ; // Don't forget the last one
            const TypeRange *tr_run = tr ;
            while ((tr_run = tr_run->GetNext()) != 0) {
                if (tr_run->IsTypeArray() && tr_run->IsPackedDimensionRange()) {
                    has_packed_dim = 1 ; // Found a packed dimension
                    break ;
                }
            }
            if (has_packed_dim && !has_unpacked_dim) {
                net->Info("Net: %s (%s) : data1", name, net->Name()) ;
            } else if (!has_packed_dim && has_unpacked_dim) {
                net->Info("Net: %s (%s) : data2 or data4", name, net->Name()) ;
            } else if (has_packed_dim && has_unpacked_dim) {
                net->Info("Net: %s (%s) : data3", name, net->Name()) ;
            }
        }
    }

    return 0 ;
}
 

test.v:

module test();
  reg data0;
  reg [2:0] data1;
  reg data2 [2:0];
  reg [2:0] data3 [2:0];
  reg data4 [2:0][0:2];
endmodule
 

Run:

$ test-linux 
-- Analyzing Verilog file 'test.v' (VERI-1482)
test.v(1): INFO: compiling module 'test' (VERI-1018)
test.v(3): INFO: Net: data1 (data1[2]) : data1
test.v(3): INFO: Net: data1 (data1[1]) : data1
test.v(3): INFO: Net: data1 (data1[0]) : data1
test.v(4): INFO: Net: data2 (data2[2]) : data2 or data4
test.v(4): INFO: Net: data2 (data2[1]) : data2 or data4
test.v(4): INFO: Net: data2 (data2[0]) : data2 or data4
test.v(5): INFO: Net: data3[2] (data3[2][2]) : data3
test.v(5): INFO: Net: data3[2] (data3[2][1]) : data3
test.v(5): INFO: Net: data3[2] (data3[2][0]) : data3
test.v(5): INFO: Net: data3[1] (data3[1][2]) : data3
test.v(5): INFO: Net: data3[1] (data3[1][1]) : data3
test.v(5): INFO: Net: data3[1] (data3[1][0]) : data3
test.v(5): INFO: Net: data3[0] (data3[0][2]) : data3
test.v(5): INFO: Net: data3[0] (data3[0][1]) : data3
test.v(5): INFO: Net: data3[0] (data3[0][0]) : data3
test.v(6): INFO: Net: data4[2] (data4[2][0]) : data2 or data4
test.v(6): INFO: Net: data4[2] (data4[2][1]) : data2 or data4
test.v(6): INFO: Net: data4[2] (data4[2][2]) : data2 or data4
test.v(6): INFO: Net: data4[1] (data4[1][0]) : data2 or data4
test.v(6): INFO: Net: data4[1] (data4[1][1]) : data2 or data4
test.v(6): INFO: Net: data4[1] (data4[1][2]) : data2 or data4
test.v(6): INFO: Net: data4[0] (data4[0][0]) : data2 or data4
test.v(6): INFO: Net: data4[0] (data4[0][1]) : data2 or data4
test.v(6): INFO: Net: data4[0] (data4[0][2]) : data2 or data4
$