Skip to content

Commit

Permalink
updating layers and adding possible new ones
Browse files Browse the repository at this point in the history
  • Loading branch information
biggsbenjamin authored and Ben Biggs committed Jul 6, 2021
1 parent dd19461 commit 0ae2798
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 28 deletions.
5 changes: 2 additions & 3 deletions fpgaconvnet_optimiser/models/layers/ExitConditionLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def __init__(
#update flags

#init modules
#TODO
self.modules = {
'redmx' : ReduceMax(self.rows_in(0), self.cols_in(0), self.channels_in(0)),
'cmp' : Compare(self.rows_in(0), self.cols_in(0), self.channels_in(0), threshold)
Expand All @@ -63,11 +62,11 @@ def layer_info(self,parameters,batch_size=1):
parameters.coarse_out = self.coarse_out

def update(self): #TODO
# exp TODO check channels are correct
# TODO check channels are correct
self.modules['redmx'].rows = self.rows_in(0)
self.modules['redmx'].cols = self.cols_in(0)
self.modules['redmx'].channels = int(self.channels[0]/self.coarse_in[0])
# div

self.modules['cmp'].rows = self.rows_in(0)
self.modules['cmp'].cols = self.cols_in(0)
self.modules['cmp'].channels = int(self.channels[0]/self.coarse_in[0])
Expand Down
144 changes: 144 additions & 0 deletions fpgaconvnet_optimiser/models/layers/SoftMaxCmpLayer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import numpy as np
import math
import pydot
import torch

from fpgaconvnet_optimiser.models.modules import Exponential
from fpgaconvnet_optimiser.models.modules import SoftMaxSum
from fpgaconvnet_optimiser.models.modules import Fork
from fpgaconvnet_optimiser.models.modules import ReduceMax
from fpgaconvnet_optimiser.models.modules import Compare
from fpgaconvnet_optimiser.models.layers import Layer

class SoftMaxCmpLayer(Layer):
def __init__(
self,
rows: int,
cols: int,
channels: int,
coarse_in: int,
coarse_out: int,
#size_in #number of values to softmax over
ctrledges: [str], #expecting list
threshold = 0.5, #TODO remove default, for the comparison module
cond_type = 'top1',
data_width = 16
):
super().__init__([rows],[cols],[channels],[coarse_in],[coarse_out])

self.ctrledges = ctrledges
self.cond_type = cond_type
self.threshold = threshold

self.ctrl_out_size = len(ctrledges)

#update flags TODO
#update parameters TODO
self.modules = {
'exp' : Exponential(self.rows_in(0), self.cols_in(0), self.channels_in(0)),
'fork_in' : Fork(self.rows_in(0), self.cols_in(0), 1, 1, 2),
'sm_sum' : SoftMaxSum(self.rows_in(0), self.cols_in(0), self.channels_in(0)),
'redmx' : ReduceMax(self.rows_in(0), self.cols_in(0), self.channels_in(0)),
'cmp' : Compare(self.rows_in(0), self.cols_in(0), self.channels_in(0), threshold),
'fork_out' : Fork(self.rows_out(0), self.cols_out(0), self.channels_in(0), 1, self.ctrl_out_size),
}

self.update()

def layer_info(self,parameters,batch_size=1):
parameters.batch_size = batch_size
parameters.buffer_depth = self.buffer_depth
parameters.rows_in = self.rows_in()
parameters.rows_in = self.rows_in()
parameters.cols_in = self.cols_in()
parameters.channels_in = self.channels_in()
parameters.rows_out = self.rows_out()
parameters.cols_out = self.cols_out()
parameters.channels_out = self.channels_out()
parameters.coarse = self.coarse_in
parameters.coarse_in = self.coarse_in
parameters.coarse_out = self.coarse_out

def update(self): #TODO
# TODO check channels are correct
self.modules['redmx'].rows = self.rows_in(0)
self.modules['redmx'].cols = self.cols_in(0)
self.modules['redmx'].channels = int(self.channels[0]/self.coarse_in[0])
#
self.modules['cmp'].rows = self.rows_in(0)
self.modules['cmp'].cols = self.cols_in(0)
self.modules['cmp'].channels = int(self.channels[0]/self.coarse_in[0])

def rates_graph(self): #TODO
rates_graph = np.zeros( shape=(5,6) , dtype=float )
# redmx
rates_graph[0,0] = self.modules['redmx'].rate_in()
rates_graph[0,1] = self.modules['redmx'].rate_out()
# cmp
rates_graph[1,1] = self.modules['cmp'].rate_in()
rates_graph[1,2] = self.modules['cmp'].rate_out()

return rates_graph

def resource(self): #TODO
redmx_rsc = self.modules['redmx'].rsc()
cmp_rsc = self.modules['cmp'].rsc()

# Total
return {
"LUT" : redmx_rsc['LUT']*self.coarse_in[0] +
cmp_rsc['LUT']*self.coarse_in[0],
"FF" : redmx_rsc['FF']*self.coarse_in[0] +
cmp_rsc['FF']*self.coarse_in[0],
"BRAM" : redmx_rsc['BRAM']*self.coarse_in[0] +
cmp_rsc['BRAM']*self.coarse_in[0],
"DSP" : redmx_rsc['DSP']*self.coarse_in[0] +
cmp_rsc['DSP']*self.coarse_in[0]
}

def visualise(self,name):
cluster = pydot.Cluster(name,label=name)

for i in range(self.coarse_in[0]): #TODO
cluster.add_node(pydot.Node( "_".join([name,"exp",str(i)]), label="exp" ))
cluster.add_node(pydot.Node( "_".join([name,"fork_i",str(i)]), label="fork_i" ))
cluster.add_edge(pydot.Edge( "_".join([name,"exp",str(i)]),
"_".join([name,"fork_i",str(i)]) ))

cluster.add_node(pydot.Node( "_".join([name,"sm_sum",str(i)]), label="sm_sum" ))
cluster.add_node(pydot.Node( "_".join([name,"redmx",str(i)]), label="redmx" ))
cluster.add_edge(pydot.Edge( "_".join([name,"fork_i",str(i)]),
"_".join([name,"sm_sum",str(i)]) ))
cluster.add_edge(pydot.Edge( "_".join([name,"fork_i",str(i)]),
"_".join([name,"redmx",str(i)]) ))

cluster.add_node(pydot.Node( "_".join([name,"cmp",str(i)]), label="cmp" ))
cluster.add_edge(pydot.Edge( "_".join([name,"redmx",str(i)]),
"_".join([name,"cmp",str(i)]) ))

cluster.add_node(pydot.Node( "_".join([name,"fork_o",str(i)]), label="fork_o" ))
cluster.add_edge(pydot.Edge( "_".join([name,"cmp",str(i)]),
"_".join([name,"fork_o",str(i)]) ))


# get nodes in and out
nodes_in = [ "_".join([name,"redmx",str(i)]) for i in range(self.coarse_in[0]) ]
#nodes_out = [ "_".join([name,"cmp",str(i)]) for i in range(self.coarse_out[0]) ]
nodes_out = [ "_".join([name,"fork_o",str(i)]) for i in range(len(self.ctrledges)) ]

return cluster, nodes_in, nodes_out

def functional_model(self, data, threshold):

assert data.shape[0] == self.rows , "ERROR (data): invalid row dimension"
assert data.shape[1] == self.cols , "ERROR (data): invalid column dimension"
assert data.shape[2] == self.channels, "ERROR (data): invalid channel dimension"

pk = softmax_layer(torch.from_numpy(data)).detach()
#get max value
top1 = torch.max(torch.from_numpy(data))
#True = early exit, drop buffered data
if top1 > threshold:
return 1.0
else:
return 0.0
56 changes: 31 additions & 25 deletions fpgaconvnet_optimiser/models/modules/Compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,29 +78,35 @@ def rsc(self):
"FF" : 0
}

def functional_model(self, data):
def functional_model(self, exp_max_set, exp_sum_set):
#exp_max is the value from reduce max
#exp_sum is from the sum of exponentials
# check input dimensionality
assert data.shape[0] == self.rows , "ERROR: invalid row dimension"
assert data.shape[1] == self.cols , "ERROR: invalid column dimension"
assert data.shape[2] == self.channels, "ERROR: invalid channel dimension"

if self.cmp_type == 'gt':
if data > self.threshold:
return 1
else:
return 0
elif self.cmp_type == 'ge':
if data >= self.threshold:
return 1
else:
return 0
elif self.cmp_type == 'lt':
if data < self.threshold:
return 1
else:
return 0
elif self.cmp_type == 'le':
if data <= self.threshold:
return 1
else:
return 0
#assert data.shape[0] == self.rows , "ERROR: invalid row dimension"
#assert data.shape[1] == self.cols , "ERROR: invalid column dimension"
#assert data.shape[2] == self.channels, "ERROR: invalid channel dimension"
out = []
print(exp_max_set, exp_sum_set)
print(self.threshold)
thr_set = np.array(exp_sum_set) * self.threshold
for (exp_max, thr) in zip(exp_max_set, thr_set):
if self.cmp_type == 'gt':
if exp_max > thr:
out.append( 1.0)
else:
out.append( 0.0)
elif self.cmp_type == 'ge':
if exp_max >= thr:
out.append( 1.0)
else:
out.append( 0.0)
elif self.cmp_type == 'lt':
if exp_max < thr:
out.append( 1.0)
else:
out.append( 0.0)
elif self.cmp_type == 'le':
if exp_max <= thr:
out.append( 1.0)
else:
out.append( 0.0)
2 changes: 2 additions & 0 deletions fpgaconvnet_optimiser/models/modules/ReduceMax.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import numpy as np
import math
import os
import torch
import torch.nn as nn

class ReduceMax(Module):
def __init__(
Expand Down
53 changes: 53 additions & 0 deletions fpgaconvnet_optimiser/models/modules/SoftMaxSum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from fpgaconvnet_optimiser.models.modules import Module
import numpy as np
import math
import os

class SoftMaxSum(Module):
def __init__(
self,
rows,
cols,
channels,
data_width=30
):

# module name
self.name = "sm_sum"

# init module
Module.__init__(self,rows,cols,channels,data_width)

def utilisation_model(self):
#TODO work out what this should be
#how should the module be laid out?
return [
1,
self.data_width,
self.data_width*self.channels
]

def pipeline_depth(self):
#TODO work out if this module can be/needs pipelining
return 0


def rsc(self):
#TODO
return {
"LUT" : 0,
"BRAM" : 0,
"DSP" : 0,
"FF" : 0
}

def functional_model(self,data):
# check input dimensionality
assert data.shape[0] == self.rows , "ERROR: invalid row dimension"
assert data.shape[1] == self.cols , "ERROR: invalid column dimension"
assert data.shape[2] == self.channels , "ERROR: invalid channel dimension"

out = np.sum(data)

return out

1 change: 1 addition & 0 deletions fpgaconvnet_optimiser/models/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@
from .Compare import Compare
from .Exponential import Exponential
from .Div import Div
from .SoftMaxSum import SoftMaxSum

0 comments on commit 0ae2798

Please sign in to comment.