Type Range example with multi-dimensional arrays
From Verific Design Automation FAQ
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 $
And here is a Perl script doing similar things, and a bit more:
#!/usr/bin/perl push (@INC,"../pm"); require "Verific.pm"; $file_name = "test.sv"; if (!Verific::veri_file::Analyze($file_name, $Verific::veri_file::SYSTEM_VERILOG)) { exit(1) ; } Verific::RuntimeFlags::SetVar("db_verilog_writer_write_internal_data", 1); Verific::RuntimeFlags::SetVar("db_add_id_vs_netbus_map", 1); if (!Verific::veri_file::ElaborateAll()) { exit(1) ; } Verific::veri_file::RemoveAllModules() ; # Get a handle to the top-level netlist $top = Verific::Netlist::PresentDesign() ; if (!$top) { print "Cannot find any handle to the top-level netlist\n"; exit(1) ; } # Print out module that we have handle to vfcprintf("INFO: last elaborated design is %s(%s)",$top->Linefile(),$top->Owner()->Name(), $top->Name()); $veriWriter = Verific::VeriWrite->new(); $veriWriter->WriteFile("netlist1.v", $top) ; my $net_vs_tr = new Verific::Map($Verific::POINTER_HASH) ; CreateTypeRangeMapping ($top, $net_vs_tr); my $net_vs_tr_mapiter = new Verific::MapItemIter($net_vs_tr); $map_item = $net_vs_tr_mapiter->First(); while ($map_item) { $net = $map_item->Key(); bless $net, Verific::Net; $name = $net->Name(); if ($net->IsNetBus()) { print ">>> netbus name: $name\n"; } else { print ">>> net name: $name\n"; } $map_value = $map_item->Value(); bless $map_value, "Verific::TypeRange"; $id = Verific::void_to_string($map_key); # print ">>>0 id: $id - typerange: $map_value\n"; ExploreTypeRange($map_value); $map_item = $net_vs_tr_mapiter->Next(); } print "<<< out now >>>\n"; exit(0) ; sub ExploreTypeRange { my ($tr) = @_; return if (!defined $tr); if ($tr->IsTypeScalar()) { print " IsTypeScalar\n"; } my $dump = $tr->Dump(); my $typename = $tr->GetTypeName(); print " typename: $typename\n"; if ($tr->IsTypeArray()) { print " IsTypeArray\n"; bless $tr, "Verific::TypeRangeArray"; if ($tr->IsPackedDimensionRange()) { print " packed dimension "; } else { print " unpacked dimension "; } my $dim = $tr->Dimension() - 1; print "#$dim: "; my $left = $tr->LeftRangeBound(); my $right = $tr->RightRangeBound(); print "left: $left - right: $right\n"; my $tr_run = $tr->GetNext(); while (($tr_run != 0)) { ExploreTypeRange($tr_run); $tr_run = $tr_run->GetNext(); } } if ($tr->IsTypeStructure()) { print " IsTypeStructure\n"; my $element_map_iter = new Verific::MapItemIter($tr->GetElementTypeRangeMap()); return if (!defined $element_map_iter); $map_item = $element_map_iter->First(); while ($map_item) { $map_key = $map_item->Key(); $element_name = Verific::void_to_string($map_key); print " element_name: $element_name\n"; $map_value = $map_item->Value(); bless $map_value, "Verific::TypeRange"; ExploreTypeRange ($map_value); $map_item = $element_map_iter->Next(); } } if ($tr->IsTypeEnum()) { print " IsTypeEnum\n"; print " You're on your own.\n"; } } sub CreateTypeRangeMapping { my ($nl, $net_vs_tr) = @_ ; return if (!defined $nl); my $netlistname = $nl->Name(); my $cellname = $nl->Owner()->Name(); my $id_vs_tr_mapiter = new Verific::MapItemIter($nl->GetTypeRangeTable()); return if (!defined $id_vs_tr_mapiter); $map_item = $id_vs_tr_mapiter->First(); while ($map_item) { $map_key = $map_item->Key(); $map_value = $map_item->Value(); bless $map_value, "Verific::TypeRange"; $id = Verific::void_to_string($map_key); $map_item = $id_vs_tr_mapiter->Next(); } my $id_vs_tr = $nl->GetTypeRangeTable(); my $id_vs_nets_mapiter = new Verific::MapItemIter($nl->GetIdNetsTable()); return if (!defined $id_vs_nets_mapiter); my $map_key ; my $map_item = $id_vs_nets_mapiter->First(); while ($map_item) { $map_key = $map_item->Key(); $map_value = $map_item->Value(); bless $map_value, "Verific::Set"; my $id = Verific::void_to_string($map_key); $design_obj_set = new Verific::DesignObjSetIter($map_value); $obj = $design_obj_set->First(); while ($obj) { my $tr = $id_vs_tr->GetValue($map_key); $net_vs_tr->Insert($obj, $tr) ; $obj = $design_obj_set->Next(); } $map_item = $id_vs_nets_mapiter->Next(); } } sub vfcprintf { my ($format) = (@_[0]); my ($lf) = (@_[1]); my @PARAMS; for (my $i = 2; $i < scalar(@_); $i++) { push(@PARAMS,"@_[$i]"); } my $lf_format = ""; if (Verific::LineFile::GetFileName($lf) && Verific::LineFile::GetLineNo($lf)) { my $lf_format = sprintf("%s(%s)",Verific::LineFile::GetFileName($lf), Verific::LineFile::GetLineNo($lf)); printf "%s: $format\n",$lf_format,@PARAMS; } else { printf "$format\n",@PARAMS; } return 0; }