|
|
|
|
|
|
|
|
|
import torch |
|
|
|
batch_size = 1 |
|
num_rows = 32 |
|
num_cols = 32 |
|
input_channels = 30 |
|
output_channels = 100 |
|
kernel_dim = 3 |
|
same_padding = kernel_dim // 2 |
|
|
|
|
|
u = (1/4)*torch.randn((batch_size, input_channels, num_rows, num_cols)) |
|
u = u.mul((2**7)) |
|
min_act = -(2**(8-1)) |
|
max_act = 2**(8-1)-1 |
|
u = u.add(0.5).floor().clamp(min=min_act, max=max_act) |
|
|
|
|
|
|
|
x = (1/4)*torch.rand((output_channels, input_channels, kernel_dim, kernel_dim)) |
|
for kr in range(0, kernel_dim): |
|
for kc in range(0, kernel_dim): |
|
for ki in range(0, input_channels): |
|
for ko in range(0, output_channels): |
|
element = x[ko,ki,kr,kc] |
|
if(element > 0.0): |
|
x[ko,ki,kr,kc] = 1 |
|
else: |
|
x[ko,ki,kr,kc] = -1 |
|
|
|
|
|
|
|
b = (1/4)*torch.randn((output_channels)) |
|
b = b.mul((2**7)) |
|
b = b.add(0.5).floor().clamp(min=min_act, max=max_act) |
|
|
|
|
|
|
|
y_act = torch.nn.functional.conv2d(u,x,bias=b, padding=same_padding) |
|
y_act = y_act.mul(128) |
|
y_act = y_act.mul(2**(0)) |
|
y_act = y_act.div(128).add(0.5).floor() |
|
|
|
y_act = torch.nn.functional.relu(y_act) |
|
|
|
|
|
allm1 = -torch.abs(x) |
|
zeta = x.add(-1).div(2.0) |
|
|
|
y_emu1 = torch.nn.functional.conv2d(2*u,zeta, bias=b,padding=same_padding) |
|
y_emu1 = y_emu1.mul(128) |
|
y_emu1 = y_emu1.mul(2**(0)) |
|
y_emu1 = y_emu1.div(128).add(0.5).floor() |
|
|
|
|
|
y_emu2 = torch.nn.functional.conv2d(u , allm1 , padding=same_padding) |
|
y_emu2 = y_emu2.mul(128) |
|
y_emu2 = y_emu2.mul(2**(0)) |
|
y_emu2 = y_emu2.div(128).add(0.5).floor() |
|
|
|
|
|
y_emu = y_emu1 - y_emu2 |
|
y_emu = y_emu.add(0.5).floor() |
|
|
|
|
|
y_emu = torch.nn.functional.relu(y_emu) |
|
|
|
print('actual output:') |
|
print('') |
|
print(y_act) |
|
print('') |
|
print('emulated output:') |
|
print('') |
|
print(y_emu) |
|
print('') |
|
print('difference:', torch.sum(torch.abs(y_act-y_emu)).numpy()) |