-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmemory_wrapper.sv
209 lines (200 loc) · 7.26 KB
/
memory_wrapper.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
`timescale 1ns/1ps
import SystemVerilogCSP::*;
module memory_wrapper(interface toMemRead, toMemWrite, toMemT, toMemX, toMemY, toMemSendData, fromMemGetData, toNOC, fromNOC);
parameter mem_delay = 15;
parameter simulating_processing_delay = 30;
parameter timesteps = 10;
parameter WIDTH = 8;
parameter WIDTH_NOC=34;
parameter WIDTH_ifmap=5, WIDTH_filter=24;
parameter PE1_addr=4'b0010, PE2_addr=4'b0110, PE3_addr=4'b1010;
parameter wrapper_addr=4'b0000, adder1_addr=4'b0001, adder2_addr=4'b0101, adder3_addr=4'b1001;
parameter input_type=2'b00, kernel_type=2'b01, mem_type=2'b10, out_type=2'b11;
parameter long_range_zeros={{6{3'b000}}, 1'b0}, short_range_zeros={4{4'b0000}};
parameter DONE=4'b1111;
//Channel #(.hsProtocol(P4PhaseBD)) intf[9:0] ();
int num_filts_x = 3;
int num_filts_y = 3;
int ofx = 3;
int ofy = 3;
int ifx = 5;
int ify = 5;
int ift = 10;
int i,j,k,t;
int read_filts = 2;
int read_ifmaps = 1; // write_ofmaps = 1 as well...
int read_mempots = 0;
int write_ofmaps = 1;
int write_mempots = 0;
int flag=0;
logic [WIDTH-1:0] byteval;
logic [WIDTH-1:0] by1, by2, by3;
logic [WIDTH_NOC-1:0] nocval;
logic [WIDTH_ifmap-1:0] ifmapvalue;
logic [WIDTH_filter-1:0] filterval;
logic spikeval;
// Weight stationary design
// TO DO: modify for your dataflow - can read an entire row (or write one) before #mem_delay
// TO DO: decide whether each Send(*)/Receive(*) is correct, or just a placeholder
initial begin
for (int i = 0; i < num_filts_x; i++) begin
for (int j = 0; j < num_filts_y; j++) begin
$display("%m Requesting filter [%d][%d] at time %d",i,j,$time);
toMemRead.Send(read_filts);
toMemX.Send(i);
toMemY.Send(j);
fromMemGetData.Receive(byteval);
case(j)
0:by1=byteval;
1:by2=byteval;
2:by3=byteval;
endcase
$display("%m Received filter[%d][%d] = %d at time %d",i,j,byteval,$time);
end
#mem_delay;
filterval={by3, by2, by1};
case(i)
0: nocval={wrapper_addr, PE1_addr, kernel_type, filterval};
1: nocval={wrapper_addr, PE2_addr, kernel_type, filterval};
2: nocval={wrapper_addr, PE3_addr, kernel_type, filterval};
endcase
toNOC.Send(nocval);
$display("%m toNOC send is %b in %t", nocval, $time);
end
$display("%m Received all filters at time %d", $time);
for (int t = 1; t <= timesteps; t++) begin
$display("%m beginning timestep t = %d at time = %d",t,$time);
// get the new ifmaps
for (int i = 0; i < ifx-2; i++) begin
for (int j = 0; j < ify; j++) begin
// TO DO: read old membrane potential (hint: you can't do it here...)
$display("%m requesting ifm[%d][%d]",i,j);
// request the input spikes
toMemRead.Send(read_ifmaps);
toMemX.Send(i);
toMemY.Send(j);
//fromMemGetData.Receive(spikeval);
//if(fromMemGetData.status != idle) begin
fromMemGetData.Receive(spikeval);
ifmapvalue[j]=spikeval;//memory->wrapper send only 1 for input spikes
//end
//else begin
// ifmapvalue[j]=0;
//end
$display("%m received ifm[%d][%d] = %b",i,j,spikeval);
//#simulating_processing_delay;
end // ify
#mem_delay; // wait for them to arrive
case(i)
0: nocval={wrapper_addr, PE1_addr, input_type, long_range_zeros, ifmapvalue};
1: nocval={wrapper_addr, PE2_addr, input_type, long_range_zeros, ifmapvalue};
2: nocval={wrapper_addr, PE3_addr, input_type, long_range_zeros, ifmapvalue};
/*default:
begin
fromNOC.Receive(nocval);
if(nocval[WIDTH_NOC-31:0]==DONE) begin
nocval={wrapper_addr, PE3_addr, input_type, ifmapvalue};
end*/
endcase
toNOC.Send(nocval);
$display("%m toNOC send is %b in %t", nocval, $time);
end // ifx
$display("%m received all ifmaps for timestep t = %d at time = %d",t,$time);
for (int i = 0; i < ofx ; i++) begin
//read old membrane potential
if(t>=2 & i==0) begin
for(int k=0; k< ofy; k++) begin
toMemRead.Send(read_mempots);
toMemX.Send(i);
toMemY.Send(k);
fromMemGetData.Receive(byteval);
case(k)
0: nocval={wrapper_addr, adder1_addr,mem_type, short_range_zeros, byteval};
1: nocval={wrapper_addr, adder2_addr,mem_type, short_range_zeros, byteval};
2: nocval={wrapper_addr, adder3_addr,mem_type, short_range_zeros, byteval};
endcase
toNOC.Send(nocval);
$display("%m toNOC send oldmem_p is %b in %t", nocval, $time);
end
end
for (int j = 0; j < ofy; j++) begin
//send membrane potential and output spikes
fromNOC.Receive(nocval);
$display("%m receive value is %b in %t", nocval, $time);
if((nocval[WIDTH_NOC-9:WIDTH_NOC-10]==out_type) & (nocval[WIDTH_NOC-31:0]==DONE)) begin
flag+=1;
if(t>=2 & i>=1 & flag<3) begin
for(int k=0; k< ofy; k++) begin
toMemRead.Send(read_mempots);
toMemX.Send(i);
toMemY.Send(k);
fromMemGetData.Receive(byteval);
case(k)
0: nocval={wrapper_addr, adder1_addr,mem_type, short_range_zeros, byteval};
1: nocval={wrapper_addr, adder2_addr,mem_type, short_range_zeros, byteval};
2: nocval={wrapper_addr, adder3_addr,mem_type, short_range_zeros, byteval};
endcase
toNOC.Send(nocval);
$display("%m toNOC send oldmem_p is %b in %t", nocval, $time);
end
end
$display("%m Done received");
if(flag<=2) begin
for(int k=0; k< ify; k++) begin
toMemRead.Send(read_ifmaps);
toMemX.Send(flag+2);
toMemY.Send(k);
fromMemGetData.Receive(spikeval);
ifmapvalue[k]=spikeval;
$display("%m received ifm[%d][%d] = %b",flag+2,k,spikeval);
end
#mem_delay; // wait for them to arrive
nocval={wrapper_addr, PE3_addr, input_type, long_range_zeros, ifmapvalue};
toNOC.Send(nocval);
$display("%m toNOC send is %b in %t", nocval, $time);
end
if(flag==3) begin
flag=0;
end
else begin
j=j-1;
end
end
else begin
if(nocval[WIDTH_NOC-9:WIDTH_NOC-10]==mem_type) begin
toMemWrite.Send(write_mempots);
toMemX.Send(i);
toMemY.Send(j);
toMemSendData.Send(nocval[WIDTH_NOC-27:0]);
$display("%m i=%d,j=%d,mem_p=%d,current timestep=%d",i,j,nocval[WIDTH_NOC-27:0],t);
if(i==2 & j==2 & flag==2) begin
j=j-1;
end
end
else if(nocval[WIDTH_NOC-9:WIDTH_NOC-10]==out_type) begin
toMemWrite.Send(write_ofmaps);
//adder -> wrapper send only 1 for output spikes
toMemX.Send(nocval[WIDTH_NOC-31:WIDTH_NOC-32]);
toMemY.Send(nocval[WIDTH_NOC-33:0]);
$display("%m addr1=%b,addr0=%b,current timestep=%d",nocval[WIDTH_NOC-31:WIDTH_NOC-32],nocval[WIDTH_NOC-33:0],t);
//toMemSendData.Send(1);
//if(i!=2 & j!=2) begin
j=j-1;
//end
end
end
end // ofy
end // ofx
$display("%m sent all output spikes and stored membrane potentials for timestep t = %d at time = %d",t,$time);
toMemT.Send(t);
$display("%m send request to advance to next timestep at time t = %d",$time);
end // t = timesteps
$display("%m done");
#mem_delay; // let memory display comparison of golden vs your outputs
$stop;
end
always begin
#200;
$display("%m working still...");
end
endmodule