Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added the logical not, and, and or operators #56

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions nngen/operator/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,62 @@
import nngen.util as util


class logical_not(bt._ElementwiseOperator):
input_chainable = True
output_chainable = True

@staticmethod
def op(strm, *args, **kwargs):
return strm.Not(*args)

def __init__(self, x, dtype=None, name=None, par=1):
shape = None
bt._ElementwiseOperator.__init__(self, x,
dtype=dtype, shape=shape, name=name, par=par)

def eval(self, memo, input_dict, **kwargs):
kwargs['x_dtype'] = self.args[0].dtype
return bt._ElementwiseOperator.eval(self, memo, input_dict, **kwargs)


class logical_and(bt._ElementwiseOperator):
input_chainable = True
output_chainable = True

@staticmethod
def op(strm, *args, **kwargs):
return strm.Land(*args)

def __init__(self, x, y, dtype=None, name=None, par=1):
shape = None
bt._ElementwiseOperator.__init__(self, x, y,
dtype=dtype, shape=shape, name=name, par=par)

def eval(self, memo, input_dict, **kwargs):
kwargs['x_dtype'] = self.args[0].dtype
kwargs['y_dtype'] = self.args[1].dtype
return bt._ElementwiseOperator.eval(self, memo, input_dict, **kwargs)


class logical_or(bt._ElementwiseOperator):
input_chainable = True
output_chainable = True

@staticmethod
def op(strm, *args, **kwargs):
return strm.Lor(*args)

def __init__(self, x, y, dtype=None, name=None, par=1):
shape = None
bt._ElementwiseOperator.__init__(self, x, y,
dtype=dtype, shape=shape, name=name, par=par)

def eval(self, memo, input_dict, **kwargs):
kwargs['x_dtype'] = self.args[0].dtype
kwargs['y_dtype'] = self.args[1].dtype
return bt._ElementwiseOperator.eval(self, memo, input_dict, **kwargs)


class add(bt._ElementwiseOperator):
"""
Returns :math:`x + y` element-wise.
Expand Down
14 changes: 14 additions & 0 deletions nngen/verify/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@
import nngen.util as util


def logical_not(x, dtype=None, name=None, par=1, x_dtype=None):
return np.logical_not(x)


def logical_and(x, y, dtype=None, name=None, par=1,
x_dtype=None, y_dtype=None):
return np.logical_and(x, y)


def logical_or(x, y, dtype=None, name=None, par=1,
x_dtype=None, y_dtype=None):
return np.logical_or(x, y)


def add(x, y, dtype=None, name=None, par=1,
x_dtype=None, y_dtype=None):

Expand Down
30 changes: 30 additions & 0 deletions tests/matrix_logical_and/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py)
ARGS=

PYTHON=python3
#PYTHON=python
#OPT=-m pdb
#OPT=-m cProfile -s time
#OPT=-m cProfile -o profile.rslt
SIMTYPE=iverilog

.PHONY: all
all: test

.PHONY: run
run:
$(PYTHON) $(OPT) $(TARGET) $(ARGS)

.PHONY: test
test:
$(PYTHON) -m pytest -vv --sim $(SIMTYPE)

.PHONY: check
check:
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
iverilog -tnull -Wall tmp.v
rm -f tmp.v

.PHONY: clean
clean:
rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd
174 changes: 174 additions & 0 deletions tests/matrix_logical_and/matrix_logical_and.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
from __future__ import absolute_import
from __future__ import print_function

import os
import sys
import functools
import math
import numpy as np

if sys.version_info.major < 3:
from itertools import izip_longest as zip_longest
else:
from itertools import zip_longest

# the next line can be removed after installation
sys.path.insert(0, os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__)))))

import nngen as ng

from veriloggen import *
import veriloggen.thread as vthread
import veriloggen.types.axi as axi


def run(a_shape=(15, 15), b_shape=(15, 15),
a_dtype=ng.int32, b_dtype=ng.int32, c_dtype=ng.int32,
par=1, axi_datawidth=32, silent=False,
filename=None, simtype='iverilog', outputfile=None):

# create target hardware
a = ng.placeholder(a_dtype, shape=a_shape, name='a')
b = ng.placeholder(b_dtype, shape=b_shape, name='b')
x = ng.sub(a, b, dtype=c_dtype, par=par)
p = ng.less(ng.full_imm((1,), 1, dtype=c_dtype, par=par), x, par=par)
q = ng.less(x, ng.full_imm((1,), 3, dtype=c_dtype, par=par), par=par)
r = ng.logical_and(p, q)
c = ng.where(r, a, b, dtype=c_dtype, par=par, name='c')

targ = ng.to_veriloggen([c], 'matrix_where', silent=silent,
config={'maxi_datawidth': axi_datawidth})

# verification data
va = np.arange(a.length, dtype=np.int64).reshape(a.shape) % [5]
vb = (np.arange(b.length, dtype=np.int64).reshape(b.shape) + [100]) % [6]

eval_outs = ng.eval([c], a=va, b=vb)
vc = eval_outs[0]

# to memory image
size_max = int(math.ceil(max(a.memory_size, b.memory_size, c.memory_size) / 4096)) * 4096
check_addr = max(a.addr, b.addr, c.addr) + size_max
size_check = size_max
tmp_addr = check_addr + size_check

memimg_datawidth = 32
mem = np.zeros([1024 * 1024 * 8 // (memimg_datawidth // 8)], dtype=np.int64)
mem = mem + [100]

axi.set_memory(mem, va, memimg_datawidth,
a_dtype.width, a.addr,
max(int(math.ceil(axi_datawidth / a_dtype.width)), par))
axi.set_memory(mem, vb, memimg_datawidth,
b_dtype.width, b.addr,
max(int(math.ceil(axi_datawidth / b_dtype.width)), par))
axi.set_memory(mem, vc, memimg_datawidth,
c_dtype.width, check_addr,
max(int(math.ceil(axi_datawidth / c_dtype.width)), par))

# test controller
m = Module('test')
params = m.copy_params(targ)
ports = m.copy_sim_ports(targ)
clk = ports['CLK']
resetn = ports['RESETN']
rst = m.Wire('RST')
rst.assign(Not(resetn))

# AXI memory model
if outputfile is None:
outputfile = os.path.splitext(os.path.basename(__file__))[0] + '.out'

memimg_name = 'memimg_' + outputfile

memory = axi.AxiMemoryModel(m, 'memory', clk, rst,
datawidth=axi_datawidth,
memimg=mem, memimg_name=memimg_name,
memimg_datawidth=memimg_datawidth)
memory.connect(ports, 'maxi')

# AXI-Slave controller
_saxi = vthread.AXIMLite(m, '_saxi', clk, rst, noio=True)
_saxi.connect(ports, 'saxi')

# timer
time_counter = m.Reg('time_counter', 32, initval=0)
seq = Seq(m, 'seq', clk, rst)
seq(
time_counter.inc()
)

num_rep = functools.reduce(lambda x, y: x * y, c.shape[:-1], 1)

def ctrl():
for i in range(100):
pass

ng.sim.set_global_addrs(_saxi, tmp_addr)

start_time = time_counter.value
ng.sim.start(_saxi)

print('# start')

ng.sim.wait(_saxi)
end_time = time_counter.value

print('# end')
print('# execution cycles: %d' % (end_time - start_time))

# verify
ok = True
for i in range(num_rep):
for j in range(c.shape[-1]):
orig = memory.read_word(i * c.aligned_shape[-1] + j,
c.addr, c_dtype.width)
check = memory.read_word(i * c.aligned_shape[-1] + j,
check_addr, c_dtype.width)

if vthread.verilog.NotEql(orig, check):
print('NG', i, j, orig, check)
ok = False
# else:
# print('OK', i, j, orig, check)

if ok:
print('# verify: PASSED')
else:
print('# verify: FAILED')

vthread.finish()

th = vthread.Thread(m, 'th_ctrl', clk, rst, ctrl)
fsm = th.start()

uut = m.Instance(targ, 'uut',
params=m.connect_params(targ),
ports=m.connect_ports(targ))

# simulation.setup_waveform(m, uut)
simulation.setup_clock(m, clk, hperiod=5)
init = simulation.setup_reset(m, resetn, m.make_reset(), period=100, polarity='low')

init.add(
Delay(1000000),
Systask('finish'),
)

# output source code
if filename is not None:
m.to_verilog(filename)

# run simulation
sim = simulation.Simulator(m, sim=simtype)
rslt = sim.run(outputfile=outputfile)
lines = rslt.splitlines()
if simtype == 'verilator' and lines[-1].startswith('-'):
rslt = '\n'.join(lines[:-1])
return rslt


if __name__ == '__main__':
rslt = run(silent=False, filename='tmp.v')
print(rslt)
47 changes: 47 additions & 0 deletions tests/matrix_logical_and/test_matrix_logical_and_int32.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from __future__ import absolute_import
from __future__ import print_function

import os
import sys

# the next line can be removed after installation
sys.path.insert(0, os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__)))))

import nngen as ng
import veriloggen

import matrix_logical_and


a_shape = (15, 15)
b_shape = (15, 15)
a_dtype = ng.int32
b_dtype = ng.int32
c_dtype = ng.int32
par = 1
axi_datawidth = 32


def test(request, silent=True):
veriloggen.reset()

simtype = request.config.getoption('--sim')

rslt = matrix_logical_and.run(a_shape, b_shape,
a_dtype, b_dtype, c_dtype,
par, axi_datawidth, silent,
filename=None, simtype=simtype,
outputfile=os.path.splitext(os.path.basename(__file__))[0] + '.out')

verify_rslt = rslt.splitlines()[-1]
assert(verify_rslt == '# verify: PASSED')


if __name__ == '__main__':
rslt = matrix_logical_and.run(a_shape, b_shape,
a_dtype, b_dtype, c_dtype,
par, axi_datawidth, silent=False,
filename='tmp.v',
outputfile=os.path.splitext(os.path.basename(__file__))[0] + '.out')
print(rslt)
30 changes: 30 additions & 0 deletions tests/matrix_logical_not/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py)
ARGS=

PYTHON=python3
#PYTHON=python
#OPT=-m pdb
#OPT=-m cProfile -s time
#OPT=-m cProfile -o profile.rslt
SIMTYPE=iverilog

.PHONY: all
all: test

.PHONY: run
run:
$(PYTHON) $(OPT) $(TARGET) $(ARGS)

.PHONY: test
test:
$(PYTHON) -m pytest -vv --sim $(SIMTYPE)

.PHONY: check
check:
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
iverilog -tnull -Wall tmp.v
rm -f tmp.v

.PHONY: clean
clean:
rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd
Loading