hls4ml icon indicating copy to clipboard operation
hls4ml copied to clipboard

Report extensions

Open thesps opened this issue 3 years ago • 6 comments

It would be nice to extend vivado_report utility to include in the extracted results:

  • per-layer resource & latency breakdown
  • Post logic synthesis resources

thesps avatar Apr 27 '21 11:04 thesps

This is something of interest for me now, so I'll take it.

Duchstf avatar May 18 '21 10:05 Duchstf

Great! I made the WIP/hacky PR #342 with the idea to make the HLS generate easier to parse reports that may be relevant.

thesps avatar May 18 '21 14:05 thesps

Hello, I'm looking into this now, could you elaborate your ideas a bit:

Basically, I think we'll just need to add another type of template to the backend templates. Or, extend the function templates we have now to be able to define both the function definition as well as the string to call it.

Wouldn't adding another type of template too time-consuming? and may cause more confusions? and I don't really understand "extend the function templates we have now to be able to define both the function definition as well as the string to call it."

Duchstf avatar Jun 03 '21 14:06 Duchstf

What I mean is, right now our templates are the strings needed to call the function, e.g. for Dense: dense_function_template = 'nnet::dense<{input_t}, {output_t}, {config}>({input}, {output}, {w}, {b});', which might become this in a project: nnet::dense<input_t, layer2_t, config2>(fc1_input, layer2_out, w2, b2);

The thing that worked in the hacky PR to get sensible names in the report is to define a new function with a unique name, and no template parameters, that just calls the specific nnet::<layer> function for that layer, e.g.

void fc1(input_t* fc1_input, layer2_t* layer2_out, weight2_t* w2, bias2_t* b2){
    #pragma HLS inline off
    nnet::dense<input_t, layer2_t, config2>(fc1_input, layer2_out, w2, b2); // fc1
}

So the writer would now need to generate the new function definition, and the call to that function, and the call to the nnet::<layer> function. You could have templates for each of those parts (which is what the hacky PR does), but it kind of doesn't make sense to hardcode them all, since the function signature defines how the function should be called afterwards, too. i.e. if the definition template is: 'void {name}({input_t}* {input}, {output_t}* {output}, {weight_t}* {w}, {bias_t}* {b})' then the call template is '{name}({input}, {output}, {w}, {b})'. So I think it should be possible to just define the 'template' once (possibly in some higher level way than just a bare string), with all the necessary parameters, like: the field for the function name, the template parameters, and the arguments - both types and names. Then the three different uses could be produced from that: the nnet::<layer> call, the layer_name definition, and the layer_name call.

thesps avatar Jun 03 '21 15:06 thesps

There is no perfect solution since we cannot know the mangled name of the templated C++ function, but perhaps a less hacky solution can be explored. Instead the heavy hammer from #342 we can get everything we want with a bit of pattern matching on files in the report directory and contain everything in the report function on the python side, not touching the writer or templates. Every function will have its base name and config + index in the corresponding .rpt/.xml file. For example, dense_array_array_ap_fixed_18_8_5_3_0_5u_config6_s_csynth.rpt (or .xml). From this name we can infer the layer was Dense and config6 gives us the unique index (6) to map it back to HLSModel from which it was created. (While we are at it, we can attach the obtained resources as an attribute of a layer so other tools that iterate over HLSModel can probe them.) This will work for all layers with io_stream. For io_parallel it won't work for Dense and BatchNormalization (probably Conv as well, but we don't consider them working with io_parallel anyway). This is because of #pragma HLS function_instantiate weights,biases in the C++ functions. This pragma doesn't really help with anything and may be removed. I believe it is a relic from a workaround that was required for an ancient version of Vivado.

vloncar avatar Jun 03 '21 15:06 vloncar

@vloncar This sounds good! I'm trying to implement it so I just have a question: in order to do the matching with the HLSModel do we need to pass the model itself into the report function? Or is there a way to do this matching from just the output directory?

Duchstf avatar Jun 06 '21 21:06 Duchstf