hls4ml
hls4ml copied to clipboard
Report extensions
It would be nice to extend vivado_report utility to include in the extracted results:
- per-layer resource & latency breakdown
- Post logic synthesis resources
This is something of interest for me now, so I'll take it.
Great! I made the WIP/hacky PR #342 with the idea to make the HLS generate easier to parse reports that may be relevant.
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."
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.
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 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?