Skip to content
Snippets Groups Projects
Commit cdeaec9c authored by Yaman Umuroglu's avatar Yaman Umuroglu
Browse files

[StreamingFC] calculate wmem/tmem, introduce no_act attribute

parent cd5b9fa8
No related branches found
No related tags found
No related merge requests found
...@@ -14,8 +14,6 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -14,8 +14,6 @@ class StreamingFCLayer_Batch(HLSCustomOp):
def get_nodeattr_types(self): def get_nodeattr_types(self):
my_attrs = { my_attrs = {
"WMEM": ("i", True, 0),
"TMEM": ("i", True, 0),
"PE": ("i", True, 0), "PE": ("i", True, 0),
"SIMD": ("i", True, 0), "SIMD": ("i", True, 0),
"MW": ("i", True, 0), "MW": ("i", True, 0),
...@@ -29,10 +27,30 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -29,10 +27,30 @@ class StreamingFCLayer_Batch(HLSCustomOp):
# use xnor-popcount for binary weights/inputs, thus treating them # use xnor-popcount for binary weights/inputs, thus treating them
# as bipolar # as bipolar
"binaryXnorMode": ("i", False, 0), "binaryXnorMode": ("i", False, 0),
# no-activation mode (produce accumulators)
"noActivation": ("i", False, 0),
} }
my_attrs.update(super().get_nodeattr_types()) my_attrs.update(super().get_nodeattr_types())
return my_attrs return my_attrs
def calc_wmem(self):
mw = self.get_nodeattr("MW")
mh = self.get_nodeattr("MH")
pe = self.get_nodeattr("PE")
simd = self.get_nodeattr("SIMD")
assert mh % pe == 0
assert mw % simd == 0
wmem = mw * mh // (pe * simd)
return wmem
def calc_tmem(self):
if self.get_nodeattr("noActivation") == 1:
return 0
else:
mh = self.get_nodeattr("MH")
pe = self.get_nodeattr("PE")
return mh // pe
def make_shape_compatible_op(self): def make_shape_compatible_op(self):
pass pass
...@@ -106,7 +124,7 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -106,7 +124,7 @@ class StreamingFCLayer_Batch(HLSCustomOp):
mh = self.get_nodeattr("MH") mh = self.get_nodeattr("MH")
pe = self.get_nodeattr("PE") pe = self.get_nodeattr("PE")
simd = self.get_nodeattr("SIMD") simd = self.get_nodeattr("SIMD")
wmem = mw * mh // (pe * simd) wmem = self.calc_wmem()
assert orig_weight_matrix.shape == (mw, mh) assert orig_weight_matrix.shape == (mw, mh)
assert mw % simd == 0 assert mw % simd == 0
assert mh % pe == 0 assert mh % pe == 0
...@@ -184,15 +202,13 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -184,15 +202,13 @@ class StreamingFCLayer_Batch(HLSCustomOp):
self.get_nodeattr("SIMD"), self.get_nodeattr("SIMD"),
export_wdt.get_hls_datatype_str(), export_wdt.get_hls_datatype_str(),
self.get_nodeattr("PE"), self.get_nodeattr("PE"),
self.get_nodeattr("WMEM"), self.calc_wmem(),
) )
) )
else: else:
f_weights.write( f_weights.write(
"static BinaryWeights<{},{},{}> weights = ".format( "static BinaryWeights<{},{},{}> weights = ".format(
self.get_nodeattr("SIMD"), self.get_nodeattr("SIMD"), self.get_nodeattr("PE"), self.calc_wmem()
self.get_nodeattr("PE"),
self.get_nodeattr("WMEM"),
) )
) )
f_weights.write(weight_hls_code) f_weights.write(weight_hls_code)
...@@ -229,7 +245,7 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -229,7 +245,7 @@ class StreamingFCLayer_Batch(HLSCustomOp):
f_thresh.write( f_thresh.write(
"static ThresholdsActivation<{},{},{},{},{},{},{}> threshs \ "static ThresholdsActivation<{},{},{},{},{},{},{}> threshs \
= ".format( = ".format(
self.get_nodeattr("TMEM"), self.calc_tmem(),
self.get_nodeattr("PE"), self.get_nodeattr("PE"),
threshold_tensor.shape[-1], threshold_tensor.shape[-1],
tdt_hls, tdt_hls,
...@@ -291,10 +307,8 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -291,10 +307,8 @@ class StreamingFCLayer_Batch(HLSCustomOp):
def global_includes(self): def global_includes(self):
self.code_gen_dict["$GLOBALS$"] = ['#include "weights.hpp"'] self.code_gen_dict["$GLOBALS$"] = ['#include "weights.hpp"']
self.code_gen_dict["$GLOBALS$"] += ['#include "activations.hpp"'] self.code_gen_dict["$GLOBALS$"] += ['#include "activations.hpp"']
if self.get_nodeattr("WMEM") != 0: self.code_gen_dict["$GLOBALS$"] += ['#include "params.h"']
# TODO find a better way of checking for no pregenerated weights if self.calc_tmem() != 0:
self.code_gen_dict["$GLOBALS$"] += ['#include "params.h"']
if self.get_nodeattr("TMEM") != 0:
# TODO find a better way of checking for no pregenerated thresholds # TODO find a better way of checking for no pregenerated thresholds
self.code_gen_dict["$GLOBALS$"] += ['#include "thresh.h"'] self.code_gen_dict["$GLOBALS$"] += ['#include "thresh.h"']
...@@ -308,8 +322,8 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -308,8 +322,8 @@ class StreamingFCLayer_Batch(HLSCustomOp):
self.get_nodeattr("MH"), self.get_nodeattr("MH"),
self.get_nodeattr("SIMD"), self.get_nodeattr("SIMD"),
self.get_nodeattr("PE"), self.get_nodeattr("PE"),
self.get_nodeattr("WMEM"), self.calc_wmem(),
self.get_nodeattr("TMEM"), self.calc_tmem(),
numReps, numReps,
) )
] ]
...@@ -344,7 +358,7 @@ class StreamingFCLayer_Batch(HLSCustomOp): ...@@ -344,7 +358,7 @@ class StreamingFCLayer_Batch(HLSCustomOp):
def docompute(self): def docompute(self):
node = self.onnx_node node = self.onnx_node
tmpl_args = self.get_template_param_values() tmpl_args = self.get_template_param_values()
if self.get_nodeattr("TMEM") == 0: if self.calc_tmem() == 0:
odtype_hls_str = self.get_output_datatype().get_hls_datatype_str() odtype_hls_str = self.get_output_datatype().get_hls_datatype_str()
threshs = "PassThroughActivation<%s>()" % odtype_hls_str threshs = "PassThroughActivation<%s>()" % odtype_hls_str
else: else:
......
...@@ -15,12 +15,9 @@ def test_code_gen_trafo(): ...@@ -15,12 +15,9 @@ def test_code_gen_trafo():
mh = 8 mh = 8
pe = 4 pe = 4
simd = 4 simd = 4
wmem = mw * mh // (pe * simd)
nf = mh // pe
sf = mw // simd
inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, sf, simd]) inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, nf, pe]) outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
node_inp_list = ["inp", "weights", "thresh"] node_inp_list = ["inp", "weights", "thresh"]
FCLayer_node = helper.make_node( FCLayer_node = helper.make_node(
"StreamingFCLayer_Batch", "StreamingFCLayer_Batch",
...@@ -35,11 +32,10 @@ def test_code_gen_trafo(): ...@@ -35,11 +32,10 @@ def test_code_gen_trafo():
MH=mh, MH=mh,
SIMD=simd, SIMD=simd,
PE=pe, PE=pe,
WMEM=wmem,
TMEM=0,
inputDataType=idt.name, inputDataType=idt.name,
weightDataType=wdt.name, weightDataType=wdt.name,
outputDataType=odt.name, outputDataType=odt.name,
noActivation=1,
) )
graph = helper.make_graph( graph = helper.make_graph(
nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp] nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp]
......
...@@ -16,12 +16,9 @@ def test_compilation_trafo(): ...@@ -16,12 +16,9 @@ def test_compilation_trafo():
mh = 8 mh = 8
pe = 4 pe = 4
simd = 4 simd = 4
wmem = mw * mh // (pe * simd)
nf = mh // pe
sf = mw // simd
inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, sf, simd]) inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, nf, pe]) outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
node_inp_list = ["inp", "weights", "thresh"] node_inp_list = ["inp", "weights", "thresh"]
FCLayer_node = helper.make_node( FCLayer_node = helper.make_node(
"StreamingFCLayer_Batch", "StreamingFCLayer_Batch",
...@@ -36,11 +33,10 @@ def test_compilation_trafo(): ...@@ -36,11 +33,10 @@ def test_compilation_trafo():
MH=mh, MH=mh,
SIMD=simd, SIMD=simd,
PE=pe, PE=pe,
WMEM=wmem,
TMEM=0,
inputDataType=idt.name, inputDataType=idt.name,
weightDataType=wdt.name, weightDataType=wdt.name,
outputDataType=odt.name, outputDataType=odt.name,
noActivation=1,
) )
graph = helper.make_graph( graph = helper.make_graph(
nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp] nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp]
......
...@@ -19,13 +19,6 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non ...@@ -19,13 +19,6 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non
mh = W.shape[1] mh = W.shape[1]
assert mh % pe == 0 assert mh % pe == 0
assert mw % simd == 0 assert mw % simd == 0
wmem = mw * mh // (pe * simd)
assert mw * mh == wmem * pe * simd
nf = mh // pe
if T is not None:
tmem = nf
else:
tmem = 0
# there are two ways to implement bipolar weights and inputs for # there are two ways to implement bipolar weights and inputs for
# StreamingFC: # StreamingFC:
...@@ -45,6 +38,7 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non ...@@ -45,6 +38,7 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non
inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw]) inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh]) outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
if T is not None: if T is not None:
no_act = 0
node_inp_list = ["inp", "weights", "thresh"] node_inp_list = ["inp", "weights", "thresh"]
if odt == DataType.BIPOLAR: if odt == DataType.BIPOLAR:
actval = 0 actval = 0
...@@ -54,6 +48,7 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non ...@@ -54,6 +48,7 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non
# no thresholds # no thresholds
node_inp_list = ["inp", "weights"] node_inp_list = ["inp", "weights"]
actval = 0 actval = 0
no_act = 1
FCLayer_node = helper.make_node( FCLayer_node = helper.make_node(
"StreamingFCLayer_Batch", "StreamingFCLayer_Batch",
node_inp_list, node_inp_list,
...@@ -65,13 +60,12 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non ...@@ -65,13 +60,12 @@ def make_single_fclayer_modelwrapper(W, pe, simd, wdt, idt, odt, T=None, tdt=Non
MH=mh, MH=mh,
SIMD=simd, SIMD=simd,
PE=pe, PE=pe,
WMEM=wmem,
TMEM=tmem,
inputDataType=export_idt.name, inputDataType=export_idt.name,
weightDataType=export_wdt.name, weightDataType=export_wdt.name,
outputDataType=odt.name, outputDataType=odt.name,
ActVal=actval, ActVal=actval,
binaryXnorMode=binary_xnor_mode, binaryXnorMode=binary_xnor_mode,
noActivation=no_act,
) )
graph = helper.make_graph( graph = helper.make_graph(
nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp] nodes=[FCLayer_node], name="fclayer_graph", inputs=[inp], outputs=[outp]
......
...@@ -10,13 +10,10 @@ def test_set_attribute(): ...@@ -10,13 +10,10 @@ def test_set_attribute():
mh = 8 mh = 8
pe = 4 pe = 4
simd = 4 simd = 4
wmem = mw * mh // (pe * simd)
nf = mh // pe
sf = mw // simd
idt = odt = wdt = DataType.BIPOLAR idt = odt = wdt = DataType.BIPOLAR
inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, sf, simd]) inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, mw])
outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, nf, pe]) outp = helper.make_tensor_value_info("outp", TensorProto.FLOAT, [1, mh])
node_inp_list = ["inp", "weights"] node_inp_list = ["inp", "weights"]
FCLayer_node = helper.make_node( FCLayer_node = helper.make_node(
...@@ -32,7 +29,6 @@ def test_set_attribute(): ...@@ -32,7 +29,6 @@ def test_set_attribute():
MH=mh, MH=mh,
SIMD=simd, SIMD=simd,
PE=pe, PE=pe,
WMEM=wmem,
inputDataType=idt.name, inputDataType=idt.name,
weightDataType=wdt.name, weightDataType=wdt.name,
outputDataType=odt.name, outputDataType=odt.name,
......
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