diff --git a/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py b/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py index 5f1697f819d229d6d7c3b8907abcb541061ecbb3..748880400d53f9bb6e90585234e2cfc21a366ba6 100644 --- a/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py +++ b/src/finn/custom_op/fpgadataflow/streamingdatawidthconverter_batch.py @@ -28,6 +28,7 @@ import os import numpy as np +import math from finn.custom_op.fpgadataflow import HLSCustomOp from finn.core.datatype import DataType @@ -447,3 +448,34 @@ class StreamingDataWidthConverter_Batch(HLSCustomOp): "DWC implementation style %s not supported, please use hls or vivado" % impl_style ) + + def lut_estimation(self): + """Calculates resource estimations for LUTs""" + impl = self.get_nodeattr("impl_style") + inw = self.get_instream_width() + outw = self.get_outstream_width() + + minw = min(inw, outw) + maxw = max(inw, outw) + + # sometimes withs aren't directly divisible + # this requires going up from input width to least common multiple + # then down to output width + intw = abs(maxw*minw) // math.gcd(maxw, minw) + + # we assume a shift-based implementation + # even if we don't use LUTs explicitly, we make some unavailable + # to other logic because they're tied into the DWC control sets + + cnt_luts = 0 + cset_luts = 0 + + if inw != intw: + cnt_luts += abs(math.ceil(math.log(inw/intw, 2))) + cset_luts += intw + if intw != outw: + cnt_luts += abs(math.ceil(math.log(intw / outw, 2))) + cset_luts += outw + + return int(cnt_luts+cset_luts) + diff --git a/src/finn/custom_op/fpgadataflow/streamingfifo.py b/src/finn/custom_op/fpgadataflow/streamingfifo.py index c9011b50d06a55c34bdd49c8ea374bdf81ea5f4f..e2f96395ad74255ad67549255608cd52737e97d9 100644 --- a/src/finn/custom_op/fpgadataflow/streamingfifo.py +++ b/src/finn/custom_op/fpgadataflow/streamingfifo.py @@ -29,6 +29,7 @@ import os import numpy as np from shutil import copy import subprocess +import math from finn.custom_op.fpgadataflow import HLSCustomOp from finn.core.datatype import DataType @@ -384,3 +385,69 @@ class StreamingFIFO(HLSCustomOp): "FIFO implementation style %s not supported, please use rtl or vivado" % impl_style ) + + def bram_estimation(self): + """Calculates resource estimation for BRAM""" + impl = self.get_nodeattr("impl_style") + ram_type = self.get_nodeattr("ram_style") + depth = self.get_nodeattr("depth") + W = self.get_instream_width() + + if impl == "rtl" or (impl == "vivado" and ram_type != "block"): + # Non-BRAM based implementation + return 0 + + if W == 1: + return math.ceil(depth / 16384) + elif W == 2: + return math.ceil(depth / 8192) + elif W <= 4: + return (math.ceil(depth / 4096)) * (math.ceil(W / 4)) + elif W <= 9: + return (math.ceil(depth / 2048)) * (math.ceil(W / 9)) + elif W <= 18 or depth > 512: + return (math.ceil(depth / 1024)) * (math.ceil(W / 18)) + else: + return (math.ceil(depth / 512)) * (math.ceil(W / 36)) + + def uram_estimation(self): + """Calculates resource estimation for URAM""" + + impl = self.get_nodeattr("impl_style") + ram_type = self.get_nodeattr("ram_style") + depth = self.get_nodeattr("depth") + W = self.get_instream_width() + + if impl == "rtl" or (impl == "vivado" and ram_type != "ultra"): + # Non-BRAM based implementation + return 0 + else: + return (math.ceil(depth / 4096)) * (math.ceil(W / 72)) + + + def bram_efficiency_estimation(self): + depth = self.get_nodeattr("depth") + W = self.get_instream_width() + bram16_est = self.bram_estimation() + if bram16_est == 0: + return 1 + wbits = W * depth + bram16_est_capacity = bram16_est * 36 * 512 + return wbits / bram16_est_capacity + + def lut_estimation(self): + """Calculates resource estimations for LUTs""" + impl = self.get_nodeattr("impl_style") + ram_type = self.get_nodeattr("ram_style") + depth = self.get_nodeattr("depth") + W = self.get_instream_width() + + address_luts = 2 * math.ceil(math.log(depth, 2)) + + if impl == "rtl" or (impl == "vivado" and ram_type == "distributed"): + ram_luts = (math.ceil(depth / 32)) * (math.ceil(W / 2)) + else: + ram_luts = 0 + + return int(address_luts + ram_luts) +