UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Scholar helmutforren
Scholar
2,088 Views
Registered: ‎06-23-2014

How do I unravel mangled signal names?

Jump to solution

I'm using Vivado 2017.1 and SystemVerilog.

 

I Open Implementation and look in the Netlist.  I find my module of interest.  I spin open and look at the Nets.  I see hundreds of signal names (Nets), but very few of them have any resemblance to the names of my signals in my SystemVerilog source code.  In essence, they are mangled.  I need to look at a specific signal, but can't figure out which mangled name represents it.  Can one or how does one get through this?

 

Note that I have a strong feeling that this is because I'm using interfaces, multi-level structures and modports.

 

Below is a whole bunch of stuff, that I've sort of separated from the main body of this post in order to try and make the post seem less long and complicated!   My actual question(s) are above this point.

 

=========================== POST SCRIPT ==============================

 

Here's a piece of the Netlist.    Now, I see see many fps960_from_MEM_fifo_push signals, so those aren't mangled.  However, I can't find in the very long list any signal names like fps960_to_MEM_fifo_pop, which are the ones for which I'm trying to debug timing.

 

MPMC Netlist Section.jpg

 

Here is the module definition, which of course describes the inputs and outputs to the module:

module MPMC #(
        parameter INCLUDE_ILA = "FALSE", 		// if TRUE then include ILA for Logic Analyzer debugging
        parameter LOCK_INPUT = 4//4//0 		// Set to 0 for NO lock.  Set to 1, 2, or 3 to lock the input
    )(
        input clk,      // System Clock = 200MHz
        input rst1,
        
        i_MEM_wr_fifo.pop input_test_fifo_pop,
        i_MEM_wr_fifo.pop input_main_flow_fifo_pop,
        i_MEM_wr_fifo.pop NUC_to_MEM_fifo_pop,
        i_MEM_wr_fifo.pop fps960_to_MEM_fifo_pop,
        i_MEM_wr_fifo.pop hist_to_MEM_fifo_pop,
        i_MEM_wr_fifo.push to_spmc_fifo_push,
        
        i_MEM_rd_fifo.pop from_spmc_fifo_pop,
        i_MEM_rd_fifo.push output_test_fifo_push,
        i_MEM_rd_fifo.push output_main_flow_fifo_push,
        i_MEM_wr_fifo.push fps960_from_MEM_fifo_push,
        i_MEM_wr_fifo.push hist_from_MEM_fifo_push,

// Testing Only
        input DDR3_Memory_Do_Test,
        input DDR3_Memory_Testing,
        input DDR3_Memory_Error,
        input CL_FVAL,
        input CL_LVAL,
        input CL_DVAL,
        input [7:0] outsel,
        
        // DEBUG ONLY
        input [4:0] debug_frame_counter,
        input debug_BOF
    );

all of the "i_*" fellows are interfaces to fifos, and the ".pop" and ".push" are modports.  

 

Here is the definition of my interfaces/structures/modports.  READ THIS FROM THE BOTTOM UP.  You'll see, for example, the "pop" modport, with members "empty", "rd_en", and "pop_data".  Well, "empty" and "rd_en" show in the Netlist, but with multiple such fifo interfaces and the degree of name mangling, I can't tell which is which.

 

//=================================================================================================================
// COMMON HEADER section
//=================================================================================================================

typedef struct packed {     // 65 BITS
    logic control_flag;   //      [64:64] Control Flag
    logic [1:0] writeflag;  //    [63:62] If 1 then write.  If 0 then read.  If 2 then pass through (neither read nor write) 
    logic [27:0] address;  //     [61:34] Memory Address
    logic [4:0] length;  //       [33:29] Memory Length (in BURSTS, 8x64bits.  This corresonds to 32 pixels)
    logic [3:0] destination;  //  [28:25] (Use `DEST Defines) Used for routing packets through demultiplexers/distributors
    logic [2:0] unused;   //      [24:22] Unused
    logic [2:0] laneidx;  //      [21:19] Communications Lane from which this packet came, numbered 0-7 for lanes 1-8.
    logic [7:0] row;      //      [18:11] Row within this lane of first data in packet
    logic [7:0] col;      //      [10:03] Column within this lane of first data in packet
    logic [2:0] frame_format;//   [02:00] Shorthand for number of rows, cols, and blanking
} t_COMMON_control_word; // named structure type

//=================================================================================================================
// MEM_wr_fifo section
//=================================================================================================================

typedef struct packed {
    logic control_flag;     //      [64:64] Control Flag should be 0 for data
    logic [63:0] data64;      //      [63:00] Data
} t_MEM_rdwr_fifo_data_word; // named structure type

typedef struct packed {
    t_COMMON_control_word [0:7] control_words; // Run from 0:7 so we see [0] on waveforme easier, so see single control_flag
} t_MEM_wr_fifo_control_word_array; // named structure type

typedef struct packed {
    t_MEM_rdwr_fifo_data_word [0:7] data_words; // Run from 0:7 because control words do
} t_MEM_rdwr_fifo_data_word_array; // named structure type

typedef union packed {
    t_MEM_wr_fifo_control_word_array control_word_array;
    t_MEM_rdwr_fifo_data_word_array data_word_array;
} t_MEM_wr_fifo_word;

typedef struct packed {
    t_MEM_wr_fifo_word data;
    logic wr_en;
    logic full;
    logic prog_full;
} t_MEM_wr_fifo_din; // named structure type

typedef struct packed {
    t_MEM_wr_fifo_word data;
    logic rd_en;
    logic empty;
} t_MEM_wr_fifo_dout; // named structure type

interface i_MEM_wr_fifo_din;    // Push into the din
    t_MEM_wr_fifo_din din;
endinterface

interface i_MEM_wr_fifo_dout;    // Pop out of the dout
    t_MEM_wr_fifo_dout dout;
endinterface

// New modport style:
interface i_MEM_wr_fifo;    
    t_MEM_wr_fifo_word push_data;
    logic wr_en;
    logic full;
    logic prog_full;

    t_MEM_wr_fifo_word pop_data;
    logic rd_en;
    logic empty;
    
    modport push (
        input full,
        input prog_full,
        output wr_en,
        output push_data
    );
    
    modport pop (
        input empty,
        output rd_en,
        input pop_data
    );
    
    modport ila (
        input full,
        input prog_full,
        input wr_en,
        input push_data,
        input empty,
        input rd_en,
        input pop_data
    );
endinterface
    
//=================================================================================================================
// MEM_rd_fifo section
//=================================================================================================================

typedef struct packed {
    t_COMMON_control_word [0:7] control_words;
} t_MEM_rd_fifo_control_word_array; // named structure type

typedef union packed {
    t_MEM_rd_fifo_control_word_array control_word_array;
    t_MEM_rdwr_fifo_data_word_array data_word_array;
} t_MEM_rd_fifo_word;

typedef struct packed {
    t_MEM_rd_fifo_word data;
    logic wr_en;
    logic full;
    logic prog_full;
} t_MEM_rd_fifo_din;

typedef struct packed {
    t_MEM_rd_fifo_word data;
    logic rd_en;
    logic empty;
} t_MEM_rd_fifo_dout;

interface i_MEM_rd_fifo_din;    // Push into the din
    t_MEM_rd_fifo_word data;
    logic wr_en;
    logic full;
    logic prog_full;
    
    modport write (
        input full,
        input prog_full,
        output wr_en,
        output data
    );
endinterface

interface i_MEM_rd_fifo_dout;    // Pop out of the dout
    t_MEM_rd_fifo_dout dout;
endinterface

// New modport style:
interface i_MEM_rd_fifo;    
    t_MEM_rd_fifo_word push_data;
    logic wr_en;
    logic full;
    logic prog_full;

    t_MEM_rd_fifo_word pop_data;
    logic rd_en;
    logic empty;
    
    modport push (
        input full,
        input prog_full,
        output wr_en,
        output push_data
    );
    
    modport pop (
        input empty,
        output rd_en,
        input pop_data
    );
    
    modport ila (
        input full,
        input prog_full,
        input wr_en,
        input push_data,
        input empty,
        input rd_en,
        input pop_data
    );
endinterface
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Historian
Historian
3,116 Views
Registered: ‎01-23-2009

Re: How do I unravel mangled signal names?

Jump to solution

Synthesis (by definition) is doing optimization of combinatorial logic. As part of that, it will merge combinatorial functionality together, pull them apart, replicated them or do any variety of Boolean optimization on them. As a result, any net that is part of a combinatorial network may simply not exist.

 

During synthesis, you have to understand exactly what is (and what isn't) preserved:

  - Ports of your design (not a module, the design) are always preserved

  - Flip-flops within a design are always preserved unless they are removed because they are redundant

     - this is true as long as you don't use any synthesis option that can modify registers

        - register retiming, register replication, register merging

        - the hierarchy of the flip-flop can change depending on how flatten_hierarchy is set

  - hierarchical instances (instances of user defined modules) as long as hierarchy isn't modified            - hierarchy is not modified if flatten_hierarchy is set to none

            - if it is set to anything else - full or rebuilt (which is the default), then this is no longer true

  - pins of hierarchical instances (as long as hierarchy isn't modified)

  - upper level nets connecting pins of hierarchical instances (as long as hierarchy isn't modified)

     - this isn't as strong as rule as the others, but seems to be true anyway

     - nets may have multiple names - the ones "highest" in the hierarchy seem to be preserved (all others may or may not be)

         - a net will have multiple "segments" with different names

 

That's pretty much it.

 

So, unless the net you are looking for falls into one of these categories, and depending on your synthesis options, it simply no longer exists - it is not that it was renamed to something else (although that is possible), it may simply no longer exist.

 

This is the reality of synthesis...

 

If you want to preserve a net, you can try placing the DONT_TOUCH attribute on it in your RTL, or MARK_DEBUG (which has the same effect), but both of these will impact the tools ability to do optimization around the net, which may have a negative effect on timing.

 

Avrum

4 Replies
Highlighted
Historian
Historian
3,117 Views
Registered: ‎01-23-2009

Re: How do I unravel mangled signal names?

Jump to solution

Synthesis (by definition) is doing optimization of combinatorial logic. As part of that, it will merge combinatorial functionality together, pull them apart, replicated them or do any variety of Boolean optimization on them. As a result, any net that is part of a combinatorial network may simply not exist.

 

During synthesis, you have to understand exactly what is (and what isn't) preserved:

  - Ports of your design (not a module, the design) are always preserved

  - Flip-flops within a design are always preserved unless they are removed because they are redundant

     - this is true as long as you don't use any synthesis option that can modify registers

        - register retiming, register replication, register merging

        - the hierarchy of the flip-flop can change depending on how flatten_hierarchy is set

  - hierarchical instances (instances of user defined modules) as long as hierarchy isn't modified            - hierarchy is not modified if flatten_hierarchy is set to none

            - if it is set to anything else - full or rebuilt (which is the default), then this is no longer true

  - pins of hierarchical instances (as long as hierarchy isn't modified)

  - upper level nets connecting pins of hierarchical instances (as long as hierarchy isn't modified)

     - this isn't as strong as rule as the others, but seems to be true anyway

     - nets may have multiple names - the ones "highest" in the hierarchy seem to be preserved (all others may or may not be)

         - a net will have multiple "segments" with different names

 

That's pretty much it.

 

So, unless the net you are looking for falls into one of these categories, and depending on your synthesis options, it simply no longer exists - it is not that it was renamed to something else (although that is possible), it may simply no longer exist.

 

This is the reality of synthesis...

 

If you want to preserve a net, you can try placing the DONT_TOUCH attribute on it in your RTL, or MARK_DEBUG (which has the same effect), but both of these will impact the tools ability to do optimization around the net, which may have a negative effect on timing.

 

Avrum

Scholar helmutforren
Scholar
2,054 Views
Registered: ‎06-23-2014

Re: How do I unravel mangled signal names?

Jump to solution

@avrumw , thanks very much for your answer.  I understand the concepts you enumerate in your bullet list.  However...

 

((((@avrumw , might you be so kind as to see my other post at https://forums.xilinx.com/t5/Timing-Analysis/Timing-report-on-a-specific-signal-path/td-p/800869 ?  I didn't say it explicitly, but my problem is this.  The design is claimed to meet timing, but when looking at actual real-time signals with ILA, I find that a couple bits being copied from one fifo to another are in error.  I am suspecting that the specific paths for these bits don't meet timing, even though the tools say my design does meet timing.))))  

 

Please help me connect your words to my understanding and need.  You say "Port of your design (not a module, the design) are always preserved".  What is the "design" in this case, and where do I see "ports" for it?  Does this mean the Top Module, perhaps?

 

You have a number of bullet items subject to "as long as hierarchy isn't modified".  Do I understand the following correctly?  Right now, my module inputs and outputs appear to be getting renamed.  If I set flatten_hierarchy to none, will that no longer happen?  That is, if I set flatten_hierarchy to none, should I subsequently be able to see my selected user-defined module inputs and outputs with original names?

 

Is there a possible performance degradation that may occur is I set flatten_hierarchy to none?

 

MEANWHILE...  When I Open Implementation, select a particular module, and then ask for a schematic, a schematic of that module is displayed.  Immediately one asks the question, "if the hierarchy was flattened, why did the tool just show a schematic for one level of the pre-flattening hierarchy?"

 

Continuing...  The schematic has I/O.  Those I/O seem to roughly correspond to my module's I/O.  This is IN CONTRAST to what you wrote.  To reconcile that contrast, I do note that the module's I/O connects mostly to fifos, and perhaps those fifos cause substantial portions of my module's I/O to be preserved.  I'll go with this belief, because it allows you to remain correct in your assertions yet my case to be somewhat special in that much of the I/O of my module seems preserved.  BUT, of course, the names aren't the same.

 

Now I'm back where I started, LOL.  I have no resolution.  

0 Kudos
Historian
Historian
2,050 Views
Registered: ‎01-23-2009

Re: How do I unravel mangled signal names?

Jump to solution

 

I am suspecting that the specific paths for these bits don't meet timing, even though the tools say my design does meet timing.

 

This is very unlikely. The static timing analysis of Vivado is very reliable. If the tool says the path meets timing, then it meets the requirements defined by your constraints. Of course, if your constraints are incorrect, then the timing is meaningless.

 

Furthermore, the timing analysis performed as part of place and route is identical to any report you can get after place and route. So if the tool says that it passes during place and route, it will say that it passes even if you explicitly ask it for the path report afterward - it is exactly the same analysis.

 

What is the "design" in this case, and where do I see "ports" for it?  Does this mean the Top Module, perhaps?

 

Yes. That is the Vivado definition of "ports".

 

If I set flatten_hierarchy to none, will that no longer happen?  That is, if I set flatten_hierarchy to none, should I subsequently be able to see my selected user-defined module inputs and outputs with original names?

 

Yes. In my opinion, flatten_hierarchy = rebuilt should NOT be the default (I have argued this with Xilinx in the past). Using flatten_hierarchy = rebuilt can improve timing if the design does not use "good" coding practice (notably registering the output of all modules), so it is set to rebuilt by default. But as you are seeing, it makes designs much more difficult to understand after synthesis... I would rather architect my design right, and set flatten_hierarchy to none (I never use anything other than none).

 

Is there a possible performance degradation that may occur is I set flatten_hierarchy to none?

 

If the design is well architected, then no. However, there are cases that this can hurt you when the design is not perfectly architected

  - the tool cannot merge logic inside and outside modules (or in two different submodules)

     - this is not a problem if you always register outputs (which is a REALLY good coding practice)

  - the tools cannot replicated logic generated in one module when it is used in another (since it cannot modify the port)

     - this sometimes can affect timing, and would need to be dealt with on a case by case basis

 

MEANWHILE...  When I Open Implementation, select a particular module, and then ask for a schematic, a schematic of that module is displayed.  Immediately one asks the question, "if the hierarchy was flattened, why did the tool just show a schematic for one level of the pre-flattening hierarchy?"

 

It was rebuilt. Which means that during synthesis it was flattened, but at the end of synthesis, the tool "rebuilds" the hierarchy - it tries to put stuff "back" into the hierarchy they came from. In the process, stuff can move from instance to instance, ports can be changed, stuff can be left at upper levels, or pretty much anything else...

 

If flatten_hierarchy is set to "full" then your synthesized result will be one giant flattened netlist with no hierarchy.

 

Continuing...  The schematic has I/O.  Those I/O seem to roughly correspond to my module's I/O.  This is IN CONTRAST to what you wrote.  To reconcile that contrast, I do note that the module's I/O connects mostly to fifos, and perhaps those fifos cause substantial portions of my module's I/O to be preserved.  I'll go with this belief, because it allows you to remain correct in your assertions yet my case to be somewhat special in that much of the I/O of my module seems preserved.  BUT, of course, the names aren't the same.

 

With flatten_hierarchy =  rebuilt, pins of hierarchical instances can be changed - they are not always changed. They can be changed if there is any optimization performed by the tool that would result in needing to change the pins of instances. If the pins of instances are not part of optimization, then they will have the same names afterward - and if the pins are going to hard blocks, then they likely cannot be part of optimization. However, that is exactly the problem - with rebuilt, you cannot count on them having their same name after synthesis - they may, or they may not.

 

Avrum

0 Kudos
Scholar helmutforren
Scholar
2,039 Views
Registered: ‎06-23-2014

Re: How do I unravel mangled signal names?

Jump to solution

@avrumw , WOW, I see you put in a lot of work on your reply.  I really do sincerely appreciate your assistance.

 

RE "I am suspecting...", "This is very unlikely...", "by your constraints".  I agree with your paragraph.  My suspicion was was that I wasn't properly constraining.  I *think* I'm properly constrained, but the ILA results show bad bits and the only way I can imagine that happening is through bad timing.  I *think* the needed timing constraint is from a particular fifo output data bit (clocked by SYSCLK) to a particular fifo input data bit (clocked by SYSCLK).  But the ILA shows the input data bit doesn't match the output data bit.  How can this be?  If it's not timing, what else could it be?  It matches most times, but not all the time.  I have a SYSCLK period of 5ns in the constraints.  If I can see the timing for this actual data bit, with start point at fifo output data bit and end point at fifo input data bit...  Indeed it ought to be less than 5ns net (including worst case delays of SYSCLK at both source and destination.)  If I *DO* find this, then I'm stuck again about what could this be?

 

BIG QUESTION: You mention "good" coding practice.  I'm think I'm being "good", but maybe I need to ask.  I'm going to go make yet another post and ask about good coding practice.  Hopefully I can manage to reference the link correctly!  Please see https://forums.xilinx.com/t5/Implementation/Good-Coding-Practice/td-p/800925

 

RE flatten hiearchy:  OK.  I understand you regarding "none" vs "rebuilt" vs "full".

0 Kudos