-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Basic nonzero-activation serialization done
- Loading branch information
Showing
4 changed files
with
160 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
nnsim.egg-info/* | ||
nnsim/__pycache__/* | ||
pruning/__pycache__/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
from nnsim.module import Module | ||
from nnsim.reg import Reg | ||
from nnsim.channel import Channel | ||
|
||
class Converter(Module): | ||
def instantiate(self, in_chn, out_chn, input_size, block_size): | ||
self.name = 'converter' | ||
|
||
# input_size is the width of the input channel | ||
# block_size is the size of blocks in memory for which we make guarantees | ||
self.input_size = input_size | ||
self.block_size = block_size | ||
|
||
# Number of times to transfer the input into the buffer | ||
self.in_sets = block_size // input_size | ||
assert(block_size % input_size == 0) # For now, ensure that input is evenly divisible | ||
self.curr_set = 0 # Counter for where we are currently in the buffer | ||
|
||
# Vars for serial output | ||
self.transfer_marker = 0 | ||
self.prev_vals = [] | ||
|
||
# Buffer. Use for accumulating input values | ||
self.buffer = [[0 for j in range(input_size)] for i in range(self.in_sets)] | ||
|
||
# channels | ||
self.in_chn = in_chn | ||
self.out_chn = out_chn | ||
|
||
def tick(self): | ||
# Once data is accumulated (placed first to prevent this from happening on the same cycle) | ||
if (self.curr_set == self.in_sets): | ||
# Do this on the last cycle | ||
if (self.transfer_marker == self.block_size): | ||
if (len(self.prev_vals) == 0): # guarantee we will always send /something/ per block | ||
self.out_chn.push([0,0,1]) | ||
else: | ||
self.prev_vals.append(1) | ||
self.out_chn.push(self.prev_vals) | ||
|
||
# Go to next block | ||
self.prev_vals = [] | ||
self.curr_set = 0 | ||
self.transfer_marker = 0 | ||
else: | ||
# pull out and check current value | ||
# if nonzero and there's room to push to the buffer, do so | ||
# hold onto values before sending so that we can send the last bit correctly | ||
# (1 if last nonzero activation in this block, 0 otherwise) | ||
j = self.transfer_marker % self.input_size | ||
i = self.transfer_marker // self.input_size | ||
curr_val = self.buffer[i][j] | ||
if (not curr_val == 0 and self.out_chn.vacancy()): | ||
if (len(self.prev_vals) > 0): | ||
self.prev_vals.append(0) | ||
self.out_chn.push(self.prev_vals) | ||
self.prev_vals = [self.transfer_marker, curr_val] | ||
self.transfer_marker += 1 | ||
elif (curr_val == 0): | ||
self.transfer_marker += 1 | ||
|
||
|
||
|
||
|
||
# Accumulate data for pruning etc | ||
if (self.in_chn.valid() and not self.curr_set == self.in_sets): | ||
data = self.in_chn.pop() | ||
#imin = self.curr_set * self.input_size | ||
#imax = imin + self.input_size | ||
self.buffer[self.curr_set] = data | ||
self.curr_set += 1 | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from random import randint | ||
|
||
from nnsim.module import Module | ||
from nnsim.reg import Reg | ||
from nnsim.channel import Channel | ||
from nnsim.simulator import Finish | ||
|
||
from converter import Converter | ||
|
||
class ConverterTB(Module): | ||
def instantiate(self): | ||
self.name = 'tb' | ||
|
||
self.input_size = 4 | ||
self.block_size = 12 | ||
self.in_sets = self.block_size // self.input_size | ||
|
||
self.in_chn = Channel() | ||
self.out_chn = Channel() | ||
|
||
self.dut = Converter(self.in_chn, self.out_chn, self.input_size, self.block_size) | ||
|
||
self.iterations = 10 | ||
self.iteration = 0 | ||
self.curr_set = 0 | ||
self.out_counter = 0 | ||
self.test_data = [[randint(1,5) if randint(0,3)>2 else 0\ | ||
for j in range(self.block_size)]\ | ||
for i in range(self.iterations)] | ||
print("Stimulus:") | ||
print("[") | ||
for i in range(len(self.test_data)): | ||
print(self.test_data[i]) | ||
print("]") | ||
|
||
def tick(self): | ||
if (self.in_chn.vacancy() and not self.iteration == self.iterations): | ||
imin = self.curr_set*self.input_size | ||
imax = imin+self.input_size | ||
data = [self.test_data[self.iteration][i] for i in range(imin, imax)] | ||
self.in_chn.push(data) | ||
|
||
self.curr_set += 1 | ||
if (self.curr_set == self.in_sets): | ||
self.curr_set = 0 | ||
self.iteration += 1 | ||
if (self.out_chn.valid()): | ||
data = self.out_chn.pop() | ||
print(data) | ||
if (data[2] == 1): | ||
self.out_counter += 1 | ||
if (self.out_counter == self.iterations): | ||
raise Finish("Check manually") | ||
|
||
if __name__ == "__main__": | ||
from nnsim.simulator import run_tb | ||
converter_tb = ConverterTB() | ||
run_tb(converter_tb, verbose=False) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
from setuptools import setup | ||
|
||
def readme(): | ||
return '' | ||
#with open('README.rst') as f: | ||
# return f.read() | ||
|
||
setup(name='nnsim', | ||
version='0.1', | ||
description='Neural network dataflow simulator', | ||
long_description=readme(), | ||
classifiers=[ | ||
'Development Status :: 3 - Alpha', | ||
'License :: OSI Approved :: MIT License', | ||
'Programming Language :: Python :: 2.7', | ||
'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', | ||
], | ||
keywords='neural-networks hardware', | ||
url='https://github.mit.edu/chiraag/nn-simulator', | ||
author='Chiraag Juvekar', | ||
author_email='[email protected]', | ||
license='MIT', | ||
packages=['nnsim'], | ||
install_requires=[], | ||
include_package_data=True, | ||
zip_safe=False) |