Skip to content
Snippets Groups Projects
Commit 1d2efd94 authored by Lucian Petrica's avatar Lucian Petrica
Browse files

Added resource estimation to DWC and FIFO

parent 8f9f536b
No related branches found
No related tags found
No related merge requests found
......@@ -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)
......@@ -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)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment