HDLRuby 2.2.17 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +19 -13
- data/lib/HDLRuby/hdr_samples/ruby_fir_hw.rb +96 -0
- data/lib/HDLRuby/hdr_samples/with_channel.rb +49 -8
- data/lib/HDLRuby/hdr_samples/with_linear.rb +48 -25
- data/lib/HDLRuby/hdr_samples/with_loop.rb +69 -0
- data/lib/HDLRuby/hdr_samples/with_memory.rb +13 -3
- data/lib/HDLRuby/hdrcc.rb +7 -11
- data/lib/HDLRuby/hruby_check.rb +25 -1
- data/lib/HDLRuby/hruby_high.rb +6 -0
- data/lib/HDLRuby/hruby_low.rb +43 -9
- data/lib/HDLRuby/hruby_low2c.rb +12 -6
- data/lib/HDLRuby/hruby_low_fix_types.rb +6 -2
- data/lib/HDLRuby/hruby_low_resolve.rb +5 -3
- data/lib/HDLRuby/hruby_low_without_concat.rb +8 -4
- data/lib/HDLRuby/hruby_types.rb +82 -72
- data/lib/HDLRuby/sim/hruby_sim.h +13 -2
- data/lib/HDLRuby/sim/hruby_sim_calc.c +104 -18
- data/lib/HDLRuby/sim/hruby_sim_core.c +12 -4
- data/lib/HDLRuby/std/channel.rb +336 -158
- data/lib/HDLRuby/std/fixpoint.rb +42 -39
- data/lib/HDLRuby/std/linear.rb +68 -0
- data/lib/HDLRuby/std/loop.rb +101 -0
- data/lib/HDLRuby/std/memory.rb +1002 -32
- data/lib/HDLRuby/std/task.rb +850 -0
- data/lib/HDLRuby/version.rb +1 -1
- metadata +6 -2
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -15,50 +15,53 @@ module HDLRuby::High::Std
|
|
15
15
|
def self.included(base)
|
16
16
|
# Performs the previous included
|
17
17
|
res = self.send(:_included_fixpoint,base)
|
18
|
-
# Now modify the Type class
|
19
|
-
::HDLRuby::High::Type.
|
20
|
-
|
21
|
-
|
18
|
+
# Now modify the Type class if not already modified.
|
19
|
+
unless ::HDLRuby::High::Type.instance_methods.include?(:"_[]_fixpoint") then
|
20
|
+
::HDLRuby::High::Type.class_eval do
|
21
|
+
# Saves the former type generation method.
|
22
|
+
alias_method :"_[]_fixpoint", :[]
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
# Handle the arguments.
|
30
|
-
arg0,arg1 = *args
|
31
|
-
if arg0.respond_to?(:to_i) then
|
32
|
-
arg0 = (arg0.to_i.abs-1)..0
|
33
|
-
end
|
34
|
-
if arg1.respond_to?(:to_i) then
|
35
|
-
arg1 = (arg1.to_i.abs-1)..0
|
36
|
-
end
|
37
|
-
# Compute the fix point sizes.
|
38
|
-
isize = (arg0.first-arg0.last).abs+1
|
39
|
-
fsize = (arg1.first-arg1.last).abs+1
|
40
|
-
# Build the type.
|
41
|
-
case(self.name)
|
42
|
-
when :bit
|
43
|
-
typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
|
44
|
-
when :unsigned
|
45
|
-
typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
|
46
|
-
when :signed
|
47
|
-
typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
|
24
|
+
# Redefine the type generation method for supporting fixed point
|
25
|
+
# type generation.
|
26
|
+
def [](*args)
|
27
|
+
if args.size == 1 then
|
28
|
+
return self.send(:"_[]_fixpoint",*args)
|
48
29
|
else
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
30
|
+
# Handle the arguments and compute the fix point sizes.
|
31
|
+
arg0,arg1 = *args
|
32
|
+
if arg0.respond_to?(:to_i) then
|
33
|
+
isize = arg0
|
34
|
+
else
|
35
|
+
isize = (arg0.first-arg0.last).abs+1
|
36
|
+
end
|
37
|
+
if arg1.respond_to?(:to_i) then
|
38
|
+
fsize = arg1
|
39
|
+
else
|
40
|
+
fsize = (arg1.first-arg1.last).abs+1
|
41
|
+
end
|
42
|
+
# Build the type.
|
43
|
+
case(self.name)
|
44
|
+
when :bit
|
45
|
+
typ = bit[isize+fsize].typedef(::HDLRuby.uniq_name)
|
46
|
+
when :unsigned
|
47
|
+
typ = unsigned[isize+fsize].typedef(::HDLRuby.uniq_name)
|
48
|
+
when :signed
|
49
|
+
typ = signed[isize+fsize].typedef(::HDLRuby.uniq_name)
|
50
|
+
else
|
51
|
+
raise "Invalid type for generating a fixed point type: #{self.name}"
|
52
|
+
end
|
53
|
+
# Redefine the multiplication and division for fixed point.
|
54
|
+
typ.define_operator(:*) do |left,right|
|
55
|
+
(left.as([isize+fsize*2])*right) >> fsize
|
56
|
+
end
|
57
|
+
typ.define_operator(:/) do |left,right|
|
58
|
+
(left.as([isize+fsize*2]) << fsize) / right
|
59
|
+
end
|
60
|
+
typ
|
57
61
|
end
|
58
|
-
typ
|
59
62
|
end
|
63
|
+
return res
|
60
64
|
end
|
61
|
-
return res
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
data/lib/HDLRuby/std/linear.rb
CHANGED
@@ -244,6 +244,74 @@ module HDLRuby::High::Std
|
|
244
244
|
end
|
245
245
|
|
246
246
|
|
247
|
+
# Declares a simple pipelined multiple mac with single right data.
|
248
|
+
#
|
249
|
+
# Can be used for the product of a martix-vector product.
|
250
|
+
function :mac_np do |typ,ev,req,ack,lefts, rights, last,
|
251
|
+
mul = proc { |x,y| x*y }, add = proc { |x,y| x+y }|
|
252
|
+
# Ensure ev is really an event.
|
253
|
+
ev = ev.posedge unless ev.is_a?(Event)
|
254
|
+
# Ensures lefts is an array.
|
255
|
+
lefts = lefts.to_a
|
256
|
+
# Ensures rights is an array.
|
257
|
+
rights = rights.to_a
|
258
|
+
# Get the size of the pipeline and ensure lefts and rights have the
|
259
|
+
# same.
|
260
|
+
size = lefts.size
|
261
|
+
if (rights.size != size) then
|
262
|
+
raise "Incompatible lefts and rights sizes: lefts size is #{size} and rights size is #{rights.size}"
|
263
|
+
end
|
264
|
+
# Declares the accumulators.
|
265
|
+
accs = size.times.map { |i| typ.inner :"acc#{i}" }
|
266
|
+
# Left value and right value.
|
267
|
+
lvs = lefts.each_with_index.map { |left,i| typ.inner :"lv#{i}" }
|
268
|
+
rvs = rights.each_with_index.map { |right,i| typ.inner :"rv#{i}" }
|
269
|
+
# typ.inner :rv
|
270
|
+
# lv and rv are valid.
|
271
|
+
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
272
|
+
# inner :rvok
|
273
|
+
rvoks = rights.each_with_index.map { |right,i| inner :"rvok#{i}" }
|
274
|
+
# Run flag
|
275
|
+
inner :run
|
276
|
+
par(ev) do
|
277
|
+
ack <= 0
|
278
|
+
run <= 0
|
279
|
+
hif(req | run) do
|
280
|
+
run <= 1
|
281
|
+
# Computation request.
|
282
|
+
lefts.zip(rights).each_with_index do |(left,right),i|
|
283
|
+
left.read(lvs[i]) { lvoks[i] <= 1 }
|
284
|
+
right.read(rvs[i]) { rvoks[i] <= 1 }
|
285
|
+
hif(lvoks[i] & rvoks[i]) do
|
286
|
+
ack <= 1
|
287
|
+
run <= 0
|
288
|
+
if (i < lefts.size-1) then
|
289
|
+
if (i>0) then
|
290
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i])) +
|
291
|
+
accs[i-1]
|
292
|
+
else
|
293
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
294
|
+
end
|
295
|
+
else
|
296
|
+
# The last is reached
|
297
|
+
seq do
|
298
|
+
accs[i] <= add.(accs[i],mul.(lvs[i],rvs[i]))
|
299
|
+
last.write(accs[i])
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
helse do
|
306
|
+
lefts.each_with_index do |left,i|
|
307
|
+
lvoks[i] <= 0
|
308
|
+
rvoks[i] <= 0
|
309
|
+
accs[i] <= 0
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
247
315
|
|
248
316
|
|
249
317
|
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'std/task.rb'
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
##
|
6
|
+
# Standard HDLRuby::High library: loops encapsulated in tasks.
|
7
|
+
#
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
## While loop: loops until +condition+ is met execution +ruby_block+.
|
11
|
+
# The loop is synchronized on +clk_e+ and initialized by +init+.
|
12
|
+
# If +condition+ is nil, then +init+ is used as +condition+.
|
13
|
+
HDLRuby::High::Std.task(:while_task) do |clk_e, init, condition, ruby_block|
|
14
|
+
# Ensure clk_e is an event, if not set it to a positive edge.
|
15
|
+
clk_e = clk_e.posedge unless clk_e.is_a?(Event)
|
16
|
+
|
17
|
+
# Ensures there is a condition.
|
18
|
+
unless condition then
|
19
|
+
condition = init
|
20
|
+
init = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
# Transform condition into a proc if it is not the case.
|
24
|
+
unless condition.is_a?(Proc) then
|
25
|
+
condition_expr = condition
|
26
|
+
condition = proc { condition_expr }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Ensures init to be a proc if not nil
|
30
|
+
init = init.to_proc unless init == nil
|
31
|
+
|
32
|
+
# Declares the signals for controlling the loop.
|
33
|
+
inner :req # Signal to set to 1 for running the loop.
|
34
|
+
|
35
|
+
# Declares the runner signals.
|
36
|
+
runner_output :req
|
37
|
+
|
38
|
+
par(clk_e) do
|
39
|
+
# Performs the loop.
|
40
|
+
hif(req) do
|
41
|
+
# By default the loop is not finished.
|
42
|
+
# If the condition is still met go on looping.
|
43
|
+
hif(condition.call,&ruby_block)
|
44
|
+
end
|
45
|
+
# # if (init) then
|
46
|
+
# # # There is an initialization, do it when there is no req.
|
47
|
+
# # helse do
|
48
|
+
# # init.call
|
49
|
+
# # end
|
50
|
+
# # end
|
51
|
+
end
|
52
|
+
|
53
|
+
# The code for reseting the task.
|
54
|
+
if (init) then
|
55
|
+
# reseter(&init)
|
56
|
+
reseter do
|
57
|
+
req <= 0
|
58
|
+
init.call
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# The code for running the task.
|
63
|
+
runner do
|
64
|
+
# top_block.unshift { req <= 0 }
|
65
|
+
req <= 1
|
66
|
+
end
|
67
|
+
|
68
|
+
# The code for checking the end of execution.
|
69
|
+
finisher do |blk|
|
70
|
+
hif(~condition.call,&blk)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
## A simplified loop: loops until +condition+ is met execution +ruby_block+.
|
78
|
+
# The loop is synchronized on +clk_e+ and initialized by +init+.
|
79
|
+
# If +condition+ is nil, then +init+ is used as +condition+.
|
80
|
+
def while_loop(clk_e, init, condition = nil, &ruby_block)
|
81
|
+
# Create the loop task.
|
82
|
+
tsk = while_task(clk_e,init,condition,ruby_block).(HDLRuby.uniq_name)
|
83
|
+
# Create the inner access port.
|
84
|
+
prt = tsk.inner HDLRuby.uniq_name
|
85
|
+
# Return the access port.
|
86
|
+
return prt
|
87
|
+
end
|
88
|
+
|
89
|
+
## Loop +num+ times executing +ruby_block+.
|
90
|
+
# The loop is synchronized on +clk_e+.
|
91
|
+
def times_loop(clk_e, num, &ruby_block)
|
92
|
+
# Compute the width of the counter.
|
93
|
+
width = num.respond_to?(:width) ? num.width : num.type.width
|
94
|
+
# Declares the counter.
|
95
|
+
cnt = [width].inner(HDLRuby.uniq_name)
|
96
|
+
# Create the loop.
|
97
|
+
return while_loop(clk_e, proc{cnt<=0}, cnt<num) do
|
98
|
+
cnt <= cnt + 1
|
99
|
+
ruby_block.call
|
100
|
+
end
|
101
|
+
end
|
data/lib/HDLRuby/std/memory.rb
CHANGED
@@ -170,6 +170,187 @@ HDLRuby::High::Std.channel(:mem_sync) do |n,typ,size,clk_e,rst,br_rsts = []|
|
|
170
170
|
end
|
171
171
|
|
172
172
|
|
173
|
+
# Flexible ROM memory of +size+ elements of +typ+ typ, syncrhonized on +clk+
|
174
|
+
# (positive and negative edges) and reset on +rst+.
|
175
|
+
# At each rising edge of +clk+ a read and a write is guaranteed to be
|
176
|
+
# completed provided they are triggered.
|
177
|
+
# +br_rsts+ are reset names on the branches, if not given, a reset input
|
178
|
+
# is added and connected to rst.
|
179
|
+
# The content of the ROM is passed through +content+ argument.
|
180
|
+
#
|
181
|
+
# NOTE:
|
182
|
+
#
|
183
|
+
# * such memories uses the following ports:
|
184
|
+
# - trig_r: read access trigger (output)
|
185
|
+
# - trig_w: write access trigger (output)
|
186
|
+
# - dbus_r: read data bus (input)
|
187
|
+
# - dbus_w: write data bus (output)
|
188
|
+
#
|
189
|
+
# * The following branches are possible (only one read and one write can
|
190
|
+
# be used per channel)
|
191
|
+
# - raddr: read by address, this channel adds the following port:
|
192
|
+
# abus_r: read address bus (output)
|
193
|
+
# - waddr: read by address, this channel adds the following port:
|
194
|
+
# abus_w: write address bus (output)
|
195
|
+
# - rinc: read by automatically incremented address.
|
196
|
+
# - winc: write by automatically incremented address.
|
197
|
+
# - rdec: read by automatically decremented address.
|
198
|
+
# - wdec: write by automatically decremented address.
|
199
|
+
# - rque: read in queue mode: automatically incremented address ensuring
|
200
|
+
# the read address is always different from the write address.
|
201
|
+
# - wque: write in queue mode: automatically incremented address ensuring
|
202
|
+
# the write address is always differnet from the read address.
|
203
|
+
#
|
204
|
+
HDLRuby::High::Std.channel(:mem_rom) do |typ,size,clk,rst,content,
|
205
|
+
br_rsts = {}|
|
206
|
+
# Ensure typ is a type.
|
207
|
+
typ = typ.to_type
|
208
|
+
# Ensure size in an integer.
|
209
|
+
size = size.to_i
|
210
|
+
# Compute the address bus width from the size.
|
211
|
+
awidth = (size-1).width
|
212
|
+
# Process the table of reset mapping for the branches.
|
213
|
+
# Ensures br_srts is a hash.
|
214
|
+
br_rsts = br_rsts.to_hash
|
215
|
+
|
216
|
+
# Declare the control signals.
|
217
|
+
# Access trigger.
|
218
|
+
inner :trig_r
|
219
|
+
# Data bus
|
220
|
+
typ.inner :dbus_r
|
221
|
+
# Address bus (or simply register)
|
222
|
+
[awidth].inner :abus_r
|
223
|
+
|
224
|
+
# Declare the ROM with its inner content.
|
225
|
+
# typ[-size].constant mem: content.map { |val| val.to_expr }
|
226
|
+
typ[-size].constant mem: content
|
227
|
+
|
228
|
+
# Processes handling the memory access.
|
229
|
+
par(clk.negedge) do
|
230
|
+
dbus_r <= mem[abus_r]
|
231
|
+
end
|
232
|
+
|
233
|
+
# The address branches.
|
234
|
+
# Read with address
|
235
|
+
brancher(:raddr) do
|
236
|
+
reader_output :trig_r, :abus_r
|
237
|
+
reader_input :dbus_r
|
238
|
+
if br_rsts[:raddr] then
|
239
|
+
rst_name = br_rsts[:raddr].to_sym
|
240
|
+
else
|
241
|
+
rst_name = rst.name
|
242
|
+
reader_input rst_name
|
243
|
+
end
|
244
|
+
|
245
|
+
# Defines the read procedure at address +addr+
|
246
|
+
# using +target+ as target of access result.
|
247
|
+
reader do |blk,addr,target|
|
248
|
+
# By default the read trigger is 0.
|
249
|
+
top_block.unshift { trig_r <= 0 }
|
250
|
+
# The read procedure.
|
251
|
+
rst = send(rst_name)
|
252
|
+
par do
|
253
|
+
hif(rst == 0) do
|
254
|
+
# No reset, so can perform the read.
|
255
|
+
hif(trig_r == 1) do
|
256
|
+
# The trigger was previously set, read ok.
|
257
|
+
target <= dbus_r
|
258
|
+
trig_r <= 0
|
259
|
+
blk.call if blk
|
260
|
+
end
|
261
|
+
helse do
|
262
|
+
# Prepare the read.
|
263
|
+
abus_r <= addr
|
264
|
+
trig_r <= 1
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# The increment branches.
|
272
|
+
# Read with increment
|
273
|
+
brancher(:rinc) do
|
274
|
+
reader_output :trig_r, :abus_r
|
275
|
+
reader_input :dbus_r
|
276
|
+
if br_rsts[:rinc] then
|
277
|
+
rst_name = br_rsts[:rinc].to_sym
|
278
|
+
else
|
279
|
+
rst_name = rst.name
|
280
|
+
reader_input rst_name
|
281
|
+
end
|
282
|
+
|
283
|
+
# Defines the read procedure at address +addr+
|
284
|
+
# using +target+ as target of access result.
|
285
|
+
reader do |blk,target|
|
286
|
+
# On reset the read trigger is 0.
|
287
|
+
rst = send(rst_name)
|
288
|
+
top_block.unshift do
|
289
|
+
# Initialize the address so that the next access is at address 0.
|
290
|
+
hif(rst==1) { abus_r <= -1 }
|
291
|
+
# Reset so switch of the access trigger.
|
292
|
+
trig_r <= 0
|
293
|
+
end
|
294
|
+
# The read procedure.
|
295
|
+
par do
|
296
|
+
hif(rst == 0) do
|
297
|
+
# No reset, so can perform the read.
|
298
|
+
hif(trig_r == 1) do
|
299
|
+
# The trigger was previously set, read ok.
|
300
|
+
target <= dbus_r
|
301
|
+
blk.call if blk
|
302
|
+
end
|
303
|
+
# Prepare the read.
|
304
|
+
abus_r <= abus_r + 1
|
305
|
+
trig_r <= 1
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# The decrement branches.
|
312
|
+
# Read with increment
|
313
|
+
brancher(:rdec) do
|
314
|
+
reader_output :trig_r, :abus_r
|
315
|
+
reader_input :dbus_r
|
316
|
+
if br_rsts[:rdec] then
|
317
|
+
rst_name = br_rsts[:rdec].to_sym
|
318
|
+
else
|
319
|
+
rst_name = rst.name
|
320
|
+
reader_input rst_name
|
321
|
+
end
|
322
|
+
|
323
|
+
# Defines the read procedure at address +addr+
|
324
|
+
# using +target+ as target of access result.
|
325
|
+
reader do |blk,target|
|
326
|
+
# On reset the read trigger is 0.
|
327
|
+
rst = send(rst_name)
|
328
|
+
top_block.unshift do
|
329
|
+
# Initialize the address so that the next access is at address 0.
|
330
|
+
hif(rst==1) { abus_r <= 0 }
|
331
|
+
# Reset so switch of the access trigger.
|
332
|
+
trig_r <= 0
|
333
|
+
end
|
334
|
+
# The read procedure.
|
335
|
+
par do
|
336
|
+
hif(rst == 0) do
|
337
|
+
# No reset, so can perform the read.
|
338
|
+
hif(trig_r == 1) do
|
339
|
+
# The trigger was previously set, read ok.
|
340
|
+
target <= dbus_r
|
341
|
+
blk.call if blk
|
342
|
+
end
|
343
|
+
# Prepare the read.
|
344
|
+
abus_r <= abus_r - 1
|
345
|
+
trig_r <= 1
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
352
|
+
|
353
|
+
|
173
354
|
|
174
355
|
|
175
356
|
|
@@ -213,28 +394,32 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
213
394
|
awidth = (size-1).width
|
214
395
|
# Process the table of reset mapping for the branches.
|
215
396
|
# puts "first br_rsts=#{br_rsts}"
|
216
|
-
if br_rsts.is_a?(Array) then
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
397
|
+
# if br_rsts.is_a?(Array) then
|
398
|
+
# # It is a list, convert it to a hash with the following order:
|
399
|
+
# # raddr, waddr, rinc, winc, rdec, wdec, rque, wque
|
400
|
+
# # When not specified the reset is +rst+ by default.
|
401
|
+
# # If there is only two entries they will be duplicated and mapped
|
402
|
+
# # as follows:
|
403
|
+
# # [raddr,waddr], [rinc,winc], [rdec,wdec], [rque,wque]
|
404
|
+
# # If there is only one entry it will be duplicated and mapped as
|
405
|
+
# # follows:
|
406
|
+
# # raddr, rinc, rdec, rque
|
407
|
+
# if br_rsts.size == 2 then
|
408
|
+
# br_rsts = br_rsts * 4
|
409
|
+
# elsif br_rsts.size == 1 then
|
410
|
+
# br_rsts = br_rsts * 8
|
411
|
+
# end
|
412
|
+
# br_rsts = { raddr: br_rsts[0], waddr: br_rsts[1],
|
413
|
+
# rinc: br_rsts[2], winc: br_rsts[3],
|
414
|
+
# rdec: br_rsts[4], wdec: br_rsts[5],
|
415
|
+
# rque: br_rsts[6], wque: br_rsts[6] }
|
416
|
+
# end
|
417
|
+
# unless br_rsts.respond_to?(:[])
|
418
|
+
# raise "Invalid reset mapping description: #{br_rsts}"
|
419
|
+
# end
|
420
|
+
#
|
421
|
+
# Ensures br_srts is a hash.
|
422
|
+
br_rsts = br_rsts.to_hash
|
238
423
|
|
239
424
|
# Declare the control signals.
|
240
425
|
# Access triggers.
|
@@ -342,7 +527,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
342
527
|
# Defines the read procedure at address +addr+
|
343
528
|
# using +target+ as target of access result.
|
344
529
|
reader do |blk,target|
|
345
|
-
#
|
530
|
+
# On reset the read trigger is 0.
|
346
531
|
rst = send(rst_name)
|
347
532
|
top_block.unshift do
|
348
533
|
# Initialize the address so that the next access is at address 0.
|
@@ -382,7 +567,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
382
567
|
# Defines the read procedure at address +addr+
|
383
568
|
# using +target+ as target of access result.
|
384
569
|
writer do |blk,target|
|
385
|
-
#
|
570
|
+
# On reset the read trigger is 0.
|
386
571
|
rst = send(rst_name)
|
387
572
|
top_block.unshift do
|
388
573
|
# Initialize the address so that the next access is at address 0.
|
@@ -420,7 +605,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
420
605
|
# Defines the read procedure at address +addr+
|
421
606
|
# using +target+ as target of access result.
|
422
607
|
reader do |blk,target|
|
423
|
-
#
|
608
|
+
# On reset the read trigger is 0.
|
424
609
|
rst = send(rst_name)
|
425
610
|
top_block.unshift do
|
426
611
|
# Initialize the address so that the next access is at address 0.
|
@@ -460,7 +645,7 @@ HDLRuby::High::Std.channel(:mem_dual) do |typ,size,clk,rst,br_rsts = {}|
|
|
460
645
|
# Defines the read procedure at address +addr+
|
461
646
|
# using +target+ as target of access result.
|
462
647
|
writer do |blk,target|
|
463
|
-
#
|
648
|
+
# On reset the read trigger is 0.
|
464
649
|
rst = send(rst_name)
|
465
650
|
top_block.unshift do
|
466
651
|
# Initialize the address so that the next access is at address 0.
|
@@ -675,7 +860,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
675
860
|
# using +target+ as target of access result.
|
676
861
|
reader do |blk,target|
|
677
862
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
678
|
-
#
|
863
|
+
# On reset the read trigger is 0.
|
679
864
|
rst = send(rst_name)
|
680
865
|
top_block.unshift do
|
681
866
|
# Initialize the address so that the next access is at address 0.
|
@@ -704,17 +889,17 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
704
889
|
rst_name = br_rsts[:winc].to_sym
|
705
890
|
else
|
706
891
|
rst_name = rst.name
|
707
|
-
|
892
|
+
writer_input rst_name
|
708
893
|
end
|
709
894
|
# Declares the address counter.
|
710
895
|
[size.width-1].inner :abus_w
|
711
|
-
|
896
|
+
writer_inout :abus_w
|
712
897
|
|
713
898
|
# Defines the write procedure at address +addr+
|
714
899
|
# using +target+ as target of access result.
|
715
900
|
writer do |blk,target|
|
716
901
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
717
|
-
#
|
902
|
+
# On reset the read trigger is 0.
|
718
903
|
rst = send(rst_name)
|
719
904
|
top_block.unshift do
|
720
905
|
# Initialize the address so that the next access is at address 0.
|
@@ -755,7 +940,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
755
940
|
# using +target+ as target of access result.
|
756
941
|
reader do |blk,target|
|
757
942
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
758
|
-
#
|
943
|
+
# On reset the read trigger is 0.
|
759
944
|
rst = send(rst_name)
|
760
945
|
top_block.unshift do
|
761
946
|
# Initialize the address so that the next access is at address 0.
|
@@ -794,7 +979,7 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
794
979
|
# using +target+ as target of access result.
|
795
980
|
writer do |blk,target|
|
796
981
|
regs = size.times.map {|i| send(:"reg_#{i}") }
|
797
|
-
#
|
982
|
+
# On reset the read trigger is 0.
|
798
983
|
rst = send(rst_name)
|
799
984
|
top_block.unshift do
|
800
985
|
# Initialize the address so that the next access is at address 0.
|
@@ -817,3 +1002,788 @@ HDLRuby::High::Std.channel(:mem_file) do |typ,size,clk,rst,br_rsts = {}|
|
|
817
1002
|
end
|
818
1003
|
|
819
1004
|
end
|
1005
|
+
|
1006
|
+
|
1007
|
+
|
1008
|
+
|
1009
|
+
# Multi-bank memory combining several dual-edge memories of +nbanks+ banks
|
1010
|
+
# of +size+ elements of +typ+ typ, syncrhonized on +clk+ (positive and
|
1011
|
+
# negative edges) and reset on +rst+.
|
1012
|
+
# at each rising edge of +clk+ a read and a write is guaranteed to be
|
1013
|
+
# completed provided they are triggered.
|
1014
|
+
# +br_rsts+ are reset names on the branches, if not given, a reset input
|
1015
|
+
# is added and connected to rst.
|
1016
|
+
#
|
1017
|
+
# NOTE:
|
1018
|
+
#
|
1019
|
+
# * such memories uses the following ports:
|
1020
|
+
# - trig_r: read access trigger (output)
|
1021
|
+
# - trig_w: write access trigger (output)
|
1022
|
+
# - dbus_r: read data bus (input)
|
1023
|
+
# - dbus_w: write data bus (output)
|
1024
|
+
#
|
1025
|
+
# * The following branches are possible (only one read and one write can
|
1026
|
+
# be used per channel)
|
1027
|
+
# - raddr: read by address, this channel adds the following port:
|
1028
|
+
# abus_r: read address bus (output)
|
1029
|
+
# - waddr: read by address, this channel adds the following port:
|
1030
|
+
# abus_w: write address bus (output)
|
1031
|
+
# - rinc: read by automatically incremented address.
|
1032
|
+
# - winc: write by automatically incremented address.
|
1033
|
+
# - rdec: read by automatically decremented address.
|
1034
|
+
# - wdec: write by automatically decremented address.
|
1035
|
+
# - rque: read in queue mode: automatically incremented address ensuring
|
1036
|
+
# the read address is always different from the write address.
|
1037
|
+
# - wque: write in queue mode: automatically incremented address ensuring
|
1038
|
+
# the write address is always differnet from the read address.
|
1039
|
+
HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
1040
|
+
# Ensure typ is a type.
|
1041
|
+
typ = typ.to_type
|
1042
|
+
# Ensure size in an integer.
|
1043
|
+
size = size.to_i
|
1044
|
+
# Compute the address bus width from the size.
|
1045
|
+
awidth = (size*nbanks-1).width
|
1046
|
+
awidth_b = (size-1).width # Bank width
|
1047
|
+
# Ensures br_srts is a hash.
|
1048
|
+
br_rsts = br_rsts.to_hash
|
1049
|
+
|
1050
|
+
# The global buses and control signals.
|
1051
|
+
[awidth].inner :abus_r, :abus_w
|
1052
|
+
typ.inner :dbus_r, :dbus_w
|
1053
|
+
inner :trig_r, :trig_w
|
1054
|
+
|
1055
|
+
# For each bank.
|
1056
|
+
nbanks.times do |id|
|
1057
|
+
# Declare the control signals.
|
1058
|
+
# Access triggers.
|
1059
|
+
inner :"trig_r_#{id}", :"trig_w_#{id}"
|
1060
|
+
# Data buses
|
1061
|
+
typ.inner :"dbus_r_#{id}", :"dbus_w_#{id}"
|
1062
|
+
# Address buses (or simply registers)
|
1063
|
+
[awidth_b].inner :"abus_r_#{id}", :"abus_w_#{id}"
|
1064
|
+
|
1065
|
+
# Declare the memory content.
|
1066
|
+
typ[-size].inner :"mem_#{id}"
|
1067
|
+
|
1068
|
+
# Processes handling the memory access.
|
1069
|
+
par(clk.negedge) do
|
1070
|
+
send(:"dbus_r_#{id}") <= send(:"mem_#{id}")[send(:"abus_r_#{id}")]
|
1071
|
+
hif(trig_w & ((abus_w % nbanks) == id)) do
|
1072
|
+
send(:"mem_#{id}")[send(:"abus_w_#{id}")] <= dbus_w
|
1073
|
+
end
|
1074
|
+
helsif(send(:"trig_w_#{id}")) do
|
1075
|
+
send(:"mem_#{id}")[send(:"abus_w_#{id}")] <= send(:"dbus_w_#{id}")
|
1076
|
+
end
|
1077
|
+
end
|
1078
|
+
end
|
1079
|
+
# Interconnect the buses and triggers
|
1080
|
+
nbanks.times do |id|
|
1081
|
+
send(:"abus_r_#{id}") <= abus_r / nbanks
|
1082
|
+
send(:"abus_w_#{id}") <= abus_w / nbanks
|
1083
|
+
end
|
1084
|
+
par do
|
1085
|
+
# By default triggers are off.
|
1086
|
+
nbanks.times do |id|
|
1087
|
+
send(:"trig_w_#{id}") <= 0
|
1088
|
+
send(:"trig_r_#{id}") <= 0
|
1089
|
+
end
|
1090
|
+
# Set the read address bus and trigger if required.
|
1091
|
+
hcase(abus_r % nbanks)
|
1092
|
+
nbanks.times do |id|
|
1093
|
+
hwhen(id) do
|
1094
|
+
dbus_r <= send(:"dbus_r_#{id}")
|
1095
|
+
send(:"trig_r_#{id}") <= trig_r
|
1096
|
+
end
|
1097
|
+
end
|
1098
|
+
end
|
1099
|
+
|
1100
|
+
|
1101
|
+
# The address branches.
|
1102
|
+
# Read with address
|
1103
|
+
brancher(:raddr) do
|
1104
|
+
reader_output :trig_r, :abus_r
|
1105
|
+
reader_input :dbus_r
|
1106
|
+
if br_rsts[:raddr] then
|
1107
|
+
rst_name = br_rsts[:raddr].to_sym
|
1108
|
+
else
|
1109
|
+
rst_name = rst.name
|
1110
|
+
reader_input rst_name
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
# Defines the read procedure at address +addr+
|
1114
|
+
# using +target+ as target of access result.
|
1115
|
+
reader do |blk,addr,target|
|
1116
|
+
# By default the read trigger is 0.
|
1117
|
+
top_block.unshift { trig_r <= 0 }
|
1118
|
+
# The read procedure.
|
1119
|
+
rst = send(rst_name)
|
1120
|
+
par do
|
1121
|
+
hif(rst == 0) do
|
1122
|
+
# No reset, so can perform the read.
|
1123
|
+
hif(trig_r == 1) do
|
1124
|
+
# The trigger was previously set, read ok.
|
1125
|
+
target <= dbus_r
|
1126
|
+
trig_r <= 0
|
1127
|
+
blk.call if blk
|
1128
|
+
end
|
1129
|
+
helse do
|
1130
|
+
# Prepare the read.
|
1131
|
+
abus_r <= addr
|
1132
|
+
trig_r <= 1
|
1133
|
+
end
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
end
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
# Write with address
|
1140
|
+
brancher(:waddr) do
|
1141
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1142
|
+
if br_rsts[:waddr] then
|
1143
|
+
rst_name = br_rsts[:waddr].to_sym
|
1144
|
+
else
|
1145
|
+
rst_name = rst.name
|
1146
|
+
writer_input rst_name
|
1147
|
+
end
|
1148
|
+
# puts "br_rsts=#{br_rsts}"
|
1149
|
+
# puts "rst_name=#{rst_name}"
|
1150
|
+
|
1151
|
+
# Defines the read procedure at address +addr+
|
1152
|
+
# using +target+ as target of access result.
|
1153
|
+
writer do |blk,addr,target|
|
1154
|
+
# By default the read trigger is 0.
|
1155
|
+
top_block.unshift { trig_w <= 0 }
|
1156
|
+
# The write procedure.
|
1157
|
+
rst = send(rst_name)
|
1158
|
+
par do
|
1159
|
+
hif(rst == 0) do
|
1160
|
+
# No reset, so can perform the write.
|
1161
|
+
hif(trig_w == 1) do
|
1162
|
+
# The trigger was previously set, write ok.
|
1163
|
+
blk.call if blk
|
1164
|
+
end
|
1165
|
+
# Prepare the write.
|
1166
|
+
abus_w <= addr
|
1167
|
+
trig_w <= 1
|
1168
|
+
dbus_w <= target
|
1169
|
+
end
|
1170
|
+
end
|
1171
|
+
end
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
# The increment branches.
|
1175
|
+
# Read with increment
|
1176
|
+
brancher(:rinc) do
|
1177
|
+
reader_output :trig_r, :abus_r
|
1178
|
+
reader_input :dbus_r
|
1179
|
+
if br_rsts[:rinc] then
|
1180
|
+
rst_name = br_rsts[:rinc].to_sym
|
1181
|
+
else
|
1182
|
+
rst_name = rst.name
|
1183
|
+
reader_input rst_name
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
# Defines the read procedure at address +addr+
|
1187
|
+
# using +target+ as target of access result.
|
1188
|
+
reader do |blk,target|
|
1189
|
+
# On reset the read trigger is 0.
|
1190
|
+
rst = send(rst_name)
|
1191
|
+
top_block.unshift do
|
1192
|
+
# Initialize the address so that the next access is at address 0.
|
1193
|
+
hif(rst==1) { abus_r <= -1 }
|
1194
|
+
# Reset so switch of the access trigger.
|
1195
|
+
trig_r <= 0
|
1196
|
+
end
|
1197
|
+
# The read procedure.
|
1198
|
+
par do
|
1199
|
+
hif(rst == 0) do
|
1200
|
+
# No reset, so can perform the read.
|
1201
|
+
hif(trig_r == 1) do
|
1202
|
+
# The trigger was previously set, read ok.
|
1203
|
+
target <= dbus_r
|
1204
|
+
blk.call if blk
|
1205
|
+
end
|
1206
|
+
# Prepare the read.
|
1207
|
+
abus_r <= abus_r + 1
|
1208
|
+
trig_r <= 1
|
1209
|
+
end
|
1210
|
+
end
|
1211
|
+
end
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
# Write with address
|
1215
|
+
brancher(:winc) do
|
1216
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1217
|
+
if br_rsts[:winc] then
|
1218
|
+
rst_name = br_rsts[:winc].to_sym
|
1219
|
+
else
|
1220
|
+
rst_name = rst.name
|
1221
|
+
writer_input rst_name
|
1222
|
+
end
|
1223
|
+
# puts "br_rsts=#{br_rsts}"
|
1224
|
+
# puts "rst_name=#{rst_name}"
|
1225
|
+
|
1226
|
+
# Defines the read procedure at address +addr+
|
1227
|
+
# using +target+ as target of access result.
|
1228
|
+
writer do |blk,target|
|
1229
|
+
# On reset the read trigger is 0.
|
1230
|
+
rst = send(rst_name)
|
1231
|
+
top_block.unshift do
|
1232
|
+
# Initialize the address so that the next access is at address 0.
|
1233
|
+
hif(rst == 1) { abus_w <= -1 }
|
1234
|
+
# Reset so switch of the access trigger.
|
1235
|
+
trig_w <= 0
|
1236
|
+
end
|
1237
|
+
# The write procedure.
|
1238
|
+
par do
|
1239
|
+
hif(rst == 0) do
|
1240
|
+
# No reset, so can perform the write.
|
1241
|
+
blk.call if blk
|
1242
|
+
# Prepare the write.
|
1243
|
+
abus_w <= abus_w + 1
|
1244
|
+
trig_w <= 1
|
1245
|
+
dbus_w <= target
|
1246
|
+
end
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
end
|
1250
|
+
|
1251
|
+
# The decrement branches.
|
1252
|
+
# Read with increment
|
1253
|
+
brancher(:rdec) do
|
1254
|
+
reader_output :trig_r, :abus_r
|
1255
|
+
reader_input :dbus_r
|
1256
|
+
if br_rsts[:rdec] then
|
1257
|
+
rst_name = br_rsts[:rdec].to_sym
|
1258
|
+
else
|
1259
|
+
rst_name = rst.name
|
1260
|
+
reader_input rst_name
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
# Defines the read procedure at address +addr+
|
1264
|
+
# using +target+ as target of access result.
|
1265
|
+
reader do |blk,target|
|
1266
|
+
# On reset the read trigger is 0.
|
1267
|
+
rst = send(rst_name)
|
1268
|
+
top_block.unshift do
|
1269
|
+
# Initialize the address so that the next access is at address 0.
|
1270
|
+
hif(rst==1) { abus_r <= 0 }
|
1271
|
+
# Reset so switch of the access trigger.
|
1272
|
+
trig_r <= 0
|
1273
|
+
end
|
1274
|
+
# The read procedure.
|
1275
|
+
par do
|
1276
|
+
hif(rst == 0) do
|
1277
|
+
# No reset, so can perform the read.
|
1278
|
+
hif(trig_r == 1) do
|
1279
|
+
# The trigger was previously set, read ok.
|
1280
|
+
target <= dbus_r
|
1281
|
+
blk.call if blk
|
1282
|
+
end
|
1283
|
+
# Prepare the read.
|
1284
|
+
abus_r <= abus_r - 1
|
1285
|
+
trig_r <= 1
|
1286
|
+
end
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
end
|
1290
|
+
|
1291
|
+
# Write with address
|
1292
|
+
brancher(:wdec) do
|
1293
|
+
writer_output :trig_w, :abus_w, :dbus_w
|
1294
|
+
if br_rsts[:wdec] then
|
1295
|
+
rst_name = br_rsts[:wdec].to_sym
|
1296
|
+
else
|
1297
|
+
rst_name = rst.name
|
1298
|
+
writer_input rst_name
|
1299
|
+
end
|
1300
|
+
# puts "br_rsts=#{br_rsts}"
|
1301
|
+
# puts "rst_name=#{rst_name}"
|
1302
|
+
|
1303
|
+
# Defines the read procedure at address +addr+
|
1304
|
+
# using +target+ as target of access result.
|
1305
|
+
writer do |blk,target|
|
1306
|
+
# On reset the read trigger is 0.
|
1307
|
+
rst = send(rst_name)
|
1308
|
+
top_block.unshift do
|
1309
|
+
# Initialize the address so that the next access is at address 0.
|
1310
|
+
hif(rst == 1) { abus_w <= 0 }
|
1311
|
+
# Reset so switch of the access trigger.
|
1312
|
+
trig_w <= 0
|
1313
|
+
end
|
1314
|
+
# The write procedure.
|
1315
|
+
par do
|
1316
|
+
hif(rst == 0) do
|
1317
|
+
# No reset, so can perform the write.
|
1318
|
+
blk.call if blk
|
1319
|
+
# Prepare the write.
|
1320
|
+
abus_w <= abus_w - 1
|
1321
|
+
trig_w <= 1
|
1322
|
+
dbus_w <= target
|
1323
|
+
end
|
1324
|
+
end
|
1325
|
+
end
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
|
1329
|
+
# Declare the branchers for accessing directly the banks.
|
1330
|
+
nbanks.times do |id|
|
1331
|
+
# Read with address.
|
1332
|
+
brancher(:"raddr_#{id}") do
|
1333
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1334
|
+
reader_input :"dbus_r_#{id}"
|
1335
|
+
if br_rsts[:"raddr_#{id}"] then
|
1336
|
+
rst_name = br_rsts[:"raddr_#{id}"].to_sym
|
1337
|
+
else
|
1338
|
+
rst_name = rst.name
|
1339
|
+
reader_input rst_name
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
# Defines the read procedure at address +addr+
|
1343
|
+
# using +target+ as target of access result.
|
1344
|
+
reader do |blk,addr,target|
|
1345
|
+
# By default the read trigger is 0.
|
1346
|
+
top_block.unshift { send(:"trig_r_#{id}") <= 0 }
|
1347
|
+
# The read procedure.
|
1348
|
+
rst = send(rst_name)
|
1349
|
+
par do
|
1350
|
+
hif(rst == 0) do
|
1351
|
+
# No reset, so can perform the read.
|
1352
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1353
|
+
# The trigger was previously set, read ok.
|
1354
|
+
target <= send(:"dbus_r_#{id}")
|
1355
|
+
send(:"trig_r_#{id}") <= 0
|
1356
|
+
blk.call if blk
|
1357
|
+
end
|
1358
|
+
helse do
|
1359
|
+
# Prepare the read.
|
1360
|
+
send(:"abus_r_#{id}") <= addr
|
1361
|
+
send(:"trig_r_#{id}") <= 1
|
1362
|
+
end
|
1363
|
+
end
|
1364
|
+
end
|
1365
|
+
end
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
# Write with address
|
1369
|
+
brancher(:"waddr_#{id}") do
|
1370
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1371
|
+
if br_rsts[:"waddr_#{id}"] then
|
1372
|
+
rst_name = br_rsts[:"waddr_#{id}"].to_sym
|
1373
|
+
else
|
1374
|
+
rst_name = rst.name
|
1375
|
+
writer_input rst_name
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
# Defines the read procedure at address +addr+
|
1379
|
+
# using +target+ as target of access result.
|
1380
|
+
writer do |blk,addr,target|
|
1381
|
+
# By default the read trigger is 0.
|
1382
|
+
top_block.unshift { send(:"trig_w_#{id}") <= 0 }
|
1383
|
+
# The write procedure.
|
1384
|
+
rst = send(rst_name)
|
1385
|
+
par do
|
1386
|
+
hif(rst == 0) do
|
1387
|
+
# No reset, so can perform the write.
|
1388
|
+
hif(send(:"trig_w_#{id}") == 1) do
|
1389
|
+
# The trigger was previously set, write ok.
|
1390
|
+
blk.call if blk
|
1391
|
+
end
|
1392
|
+
# Prepare the write.
|
1393
|
+
send(:"abus_w_#{id}") <= addr
|
1394
|
+
send(:"trig_w_#{id}") <= 1
|
1395
|
+
send(:"dbus_w_#{id}") <= target
|
1396
|
+
end
|
1397
|
+
end
|
1398
|
+
end
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
# The increment branches.
|
1402
|
+
# Read with increment
|
1403
|
+
brancher(:"rinc_#{id}") do
|
1404
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1405
|
+
reader_input :"dbus_r_#{id}"
|
1406
|
+
if br_rsts[:"rinc_#{id}"] then
|
1407
|
+
rst_name = br_rsts[:"rinc_#{id}"].to_sym
|
1408
|
+
else
|
1409
|
+
rst_name = rst.name
|
1410
|
+
reader_input rst_name
|
1411
|
+
end
|
1412
|
+
|
1413
|
+
# Defines the read procedure at address +addr+
|
1414
|
+
# using +target+ as target of access result.
|
1415
|
+
reader do |blk,target|
|
1416
|
+
# On reset the read trigger is 0.
|
1417
|
+
rst = send(rst_name)
|
1418
|
+
top_block.unshift do
|
1419
|
+
# Initialize the address so that the next access is at address 0.
|
1420
|
+
hif(rst==1) { send(:"abus_r_#{id}") <= -1 }
|
1421
|
+
# Reset so switch of the access trigger.
|
1422
|
+
send(:"trig_r_#{id}") <= 0
|
1423
|
+
end
|
1424
|
+
# The read procedure.
|
1425
|
+
par do
|
1426
|
+
hif(rst == 0) do
|
1427
|
+
# No reset, so can perform the read.
|
1428
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1429
|
+
# The trigger was previously set, read ok.
|
1430
|
+
target <= send(:"dbus_r_#{id}")
|
1431
|
+
blk.call if blk
|
1432
|
+
end
|
1433
|
+
# Prepare the read.
|
1434
|
+
send(:"abus_r_#{id}") <= send(:"abus_r_#{id}") + 1
|
1435
|
+
send(:"trig_r_#{id}") <= 1
|
1436
|
+
end
|
1437
|
+
end
|
1438
|
+
end
|
1439
|
+
end
|
1440
|
+
|
1441
|
+
# Write with address
|
1442
|
+
brancher(:"winc_#{id}") do
|
1443
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1444
|
+
if br_rsts[:"winc_#{id}"] then
|
1445
|
+
rst_name = br_rsts[:"winc_#{id}"].to_sym
|
1446
|
+
else
|
1447
|
+
rst_name = rst.name
|
1448
|
+
writer_input rst_name
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
# Defines the read procedure at address +addr+
|
1452
|
+
# using +target+ as target of access result.
|
1453
|
+
writer do |blk,target|
|
1454
|
+
# On reset the read trigger is 0.
|
1455
|
+
rst = send(rst_name)
|
1456
|
+
top_block.unshift do
|
1457
|
+
# Initialize the address so that the next access is at address 0.
|
1458
|
+
hif(rst == 1) { send(:"abus_w_#{id}") <= -1 }
|
1459
|
+
# Reset so switch of the access trigger.
|
1460
|
+
send(:"trig_w_#{id}") <= 0
|
1461
|
+
end
|
1462
|
+
# The write procedure.
|
1463
|
+
par do
|
1464
|
+
hif(rst == 0) do
|
1465
|
+
# No reset, so can perform the write.
|
1466
|
+
blk.call if blk
|
1467
|
+
# Prepare the write.
|
1468
|
+
send(:"abus_w_#{id}") <= send(:"abus_w_#{id}") + 1
|
1469
|
+
send(:"trig_w_#{id}") <= 1
|
1470
|
+
send(:"dbus_w_#{id}") <= target
|
1471
|
+
end
|
1472
|
+
end
|
1473
|
+
end
|
1474
|
+
end
|
1475
|
+
|
1476
|
+
# The decrement branches.
|
1477
|
+
# Read with increment
|
1478
|
+
brancher(:"rdec_#{id}") do
|
1479
|
+
reader_output :"trig_r_#{id}", :"abus_r_#{id}"
|
1480
|
+
reader_input :"dbus_r_#{id}"
|
1481
|
+
if br_rsts[:"rdec_#{id}"] then
|
1482
|
+
rst_name = br_rsts[:"rdec_#{id}"].to_sym
|
1483
|
+
else
|
1484
|
+
rst_name = rst.name
|
1485
|
+
reader_input rst_name
|
1486
|
+
end
|
1487
|
+
|
1488
|
+
# Defines the read procedure at address +addr+
|
1489
|
+
# using +target+ as target of access result.
|
1490
|
+
reader do |blk,target|
|
1491
|
+
# On reset the read trigger is 0.
|
1492
|
+
rst = send(rst_name)
|
1493
|
+
top_block.unshift do
|
1494
|
+
# Initialize the address so that the next access is at address 0.
|
1495
|
+
hif(rst==1) { send(:"abus_r_#{id}") <= 0 }
|
1496
|
+
# Reset so switch of the access trigger.
|
1497
|
+
send(:"trig_r_#{id}") <= 0
|
1498
|
+
end
|
1499
|
+
# The read procedure.
|
1500
|
+
par do
|
1501
|
+
hif(rst == 0) do
|
1502
|
+
# No reset, so can perform the read.
|
1503
|
+
hif(send(:"trig_r_#{id}") == 1) do
|
1504
|
+
# The trigger was previously set, read ok.
|
1505
|
+
target <= send(:"dbus_r_#{id}")
|
1506
|
+
blk.call if blk
|
1507
|
+
end
|
1508
|
+
# Prepare the read.
|
1509
|
+
send(:"abus_r_#{id}") <= send(:"abus_r_#{id}") - 1
|
1510
|
+
send(:"trig_r_#{id}") <= 1
|
1511
|
+
end
|
1512
|
+
end
|
1513
|
+
end
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
# Write with address
|
1517
|
+
brancher(:"wdec_#{id}") do
|
1518
|
+
writer_output :"trig_w_#{id}", :"abus_w_#{id}", :"dbus_w_#{id}"
|
1519
|
+
if br_rsts[:"wdec_#{id}"] then
|
1520
|
+
rst_name = br_rsts[:"wdec_#{id}"].to_sym
|
1521
|
+
else
|
1522
|
+
rst_name = rst.name
|
1523
|
+
writer_input rst_name
|
1524
|
+
end
|
1525
|
+
|
1526
|
+
# Defines the read procedure at address +addr+
|
1527
|
+
# using +target+ as target of access result.
|
1528
|
+
writer do |blk,target|
|
1529
|
+
# On reset the read trigger is 0.
|
1530
|
+
rst = send(rst_name)
|
1531
|
+
top_block.unshift do
|
1532
|
+
# Initialize the address so that the next access is at address 0.
|
1533
|
+
hif(rst == 1) { send(:"abus_w_#{id}") <= 0 }
|
1534
|
+
# Reset so switch of the access trigger.
|
1535
|
+
trig_w <= 0
|
1536
|
+
end
|
1537
|
+
# The write procedure.
|
1538
|
+
par do
|
1539
|
+
hif(rst == 0) do
|
1540
|
+
# No reset, so can perform the write.
|
1541
|
+
blk.call if blk
|
1542
|
+
# Prepare the write.
|
1543
|
+
send(:"abus_w_#{id}") <= send(:"abus_w_#{id}") - 1
|
1544
|
+
send(:"trig_w_#{id}") <= 1
|
1545
|
+
send(:"dbus_w_#{id}") <= target
|
1546
|
+
end
|
1547
|
+
end
|
1548
|
+
end
|
1549
|
+
end
|
1550
|
+
end
|
1551
|
+
|
1552
|
+
end
|
1553
|
+
|
1554
|
+
# HDLRuby::High::Std.channel(:mem_bank) do |typ,nbanks,size,clk,rst,br_rsts = {}|
|
1555
|
+
# # Ensure typ is a type.
|
1556
|
+
# typ = typ.to_type
|
1557
|
+
# # Ensure nbank is an integer.
|
1558
|
+
# nbanks = nbanks.to_i
|
1559
|
+
# # Ensure size in an integer.
|
1560
|
+
# size = size.to_i
|
1561
|
+
# # Compute the address bus width from the size.
|
1562
|
+
# awidth = (size-1).width
|
1563
|
+
# # # Process the table of reset mapping for the branches.
|
1564
|
+
# # # puts "first br_rsts=#{br_rsts}"
|
1565
|
+
# # if br_rsts.is_a?(Array) then
|
1566
|
+
# # # It is a list, convert it to a hash with the following order:
|
1567
|
+
# # # raddr, waddr, rinc, winc, rdec, wdec, rque, wque
|
1568
|
+
# # # If there is only two entries they will be duplicated and mapped
|
1569
|
+
# # # as follows:
|
1570
|
+
# # # [raddr,waddr], [rinc,winc], [rdec,wdec], [rque,wque]
|
1571
|
+
# # # If there is only one entry it will be duplicated and mapped as
|
1572
|
+
# # # follows:
|
1573
|
+
# # # raddr, rinc, rdec, rque
|
1574
|
+
# # if br_rsts.size == 2 then
|
1575
|
+
# # br_rsts = br_rsts * 4
|
1576
|
+
# # elsif br_rsts.size == 1 then
|
1577
|
+
# # br_rsts = br_rsts * 8
|
1578
|
+
# # end
|
1579
|
+
# # br_rsts = { raddr: br_rsts[0], waddr: br_rsts[1],
|
1580
|
+
# # rinc: br_rsts[2], winc: br_rsts[3],
|
1581
|
+
# # rdec: br_rsts[4], wdec: br_rsts[5],
|
1582
|
+
# # rque: br_rsts[6], wque: br_rsts[6] }
|
1583
|
+
# # end
|
1584
|
+
# # unless br_rsts.respond_to?(:[])
|
1585
|
+
# # raise "Invalid reset mapping description: #{br_rsts}"
|
1586
|
+
# # end
|
1587
|
+
# # Ensures br_rsts is a hash.
|
1588
|
+
# br_rsts = br_rsts.to_hash
|
1589
|
+
#
|
1590
|
+
# # Declares the banks.
|
1591
|
+
# banks = nbanks.times.map do |id|
|
1592
|
+
# # Extract the resets corresponding to the bank.
|
1593
|
+
# cur_br_rsts = {}
|
1594
|
+
# br_rsts.each do |k,v|
|
1595
|
+
# num = k.to_s[/\d+$/]
|
1596
|
+
# if num && num.to_i == id then
|
1597
|
+
# cur_br_rsts[k.to_s.chomp[num]] = v
|
1598
|
+
# end
|
1599
|
+
# end
|
1600
|
+
# # Declare the bank.
|
1601
|
+
# mem_dual(typ,size,clk,rst, cur_br_rsts).(HDLRuby.uniq_name)
|
1602
|
+
# end
|
1603
|
+
#
|
1604
|
+
# # Declare the branchers for accessing directly the banks.
|
1605
|
+
# banks.each_with_index do |bank,id|
|
1606
|
+
# brancher(id,bank)
|
1607
|
+
# end
|
1608
|
+
#
|
1609
|
+
# # Generate the gobal access to the memory.
|
1610
|
+
#
|
1611
|
+
# # The address branches.
|
1612
|
+
# # Read with address
|
1613
|
+
# brancher(:raddr) do
|
1614
|
+
# # Create the read branch for each bank.
|
1615
|
+
# bank_brs = banks.map do |bank|
|
1616
|
+
# bank.branch(:raddr).inner HDLRuby.uniq_name
|
1617
|
+
# end
|
1618
|
+
# # Defines the read procedure at address +addr+
|
1619
|
+
# # using +target+ as target of access result.
|
1620
|
+
# reader do |blk,addr,target|
|
1621
|
+
# # Select the bank depending on the address.
|
1622
|
+
# hcase(addr / nbanks)
|
1623
|
+
# nbanks.times do |i|
|
1624
|
+
# hwhen(i) do
|
1625
|
+
# bank_brs[i].read(addr % nbanks,target,&blk)
|
1626
|
+
# end
|
1627
|
+
# end
|
1628
|
+
# end
|
1629
|
+
# end
|
1630
|
+
# # Write with address
|
1631
|
+
# brancher(:waddr) do
|
1632
|
+
# # Create the write branch for each bank.
|
1633
|
+
# bank_brs = banks.map do |bank|
|
1634
|
+
# bank.branch(:waddr).inner HDLRuby.uniq_name
|
1635
|
+
# end
|
1636
|
+
# # Defines the read procedure at address +addr+
|
1637
|
+
# # using +target+ as target of access result.
|
1638
|
+
# writer do |blk,addr,target|
|
1639
|
+
# # Select the bank depending on the address.
|
1640
|
+
# hcase(addr / nbanks)
|
1641
|
+
# nbanks.times do |i|
|
1642
|
+
# hwhen(i) do
|
1643
|
+
# bank_brs[i].write(addr % nbanks,target,&blk)
|
1644
|
+
# end
|
1645
|
+
# end
|
1646
|
+
# end
|
1647
|
+
# end
|
1648
|
+
#
|
1649
|
+
#
|
1650
|
+
# # Address buses (or simply registers) for increment/decrement accesses
|
1651
|
+
# [awidth].inner :abus_r, :abus_w
|
1652
|
+
#
|
1653
|
+
# # The increment branches.
|
1654
|
+
# # Read with increment
|
1655
|
+
# brancher(:rinc) do
|
1656
|
+
# reader_output :abus_r
|
1657
|
+
# if br_rsts[:rinc] then
|
1658
|
+
# rst_name = br_rsts[:rinc].to_sym
|
1659
|
+
# else
|
1660
|
+
# rst_name = rst.name
|
1661
|
+
# reader_input rst_name
|
1662
|
+
# end
|
1663
|
+
# # Create the write branch for each bank.
|
1664
|
+
# bank_brs = banks.map do |bank|
|
1665
|
+
# bank.branch(:raddr).inner HDLRuby.uniq_name
|
1666
|
+
# end
|
1667
|
+
#
|
1668
|
+
# # Defines the read procedure at address +addr+
|
1669
|
+
# # using +target+ as target of access result.
|
1670
|
+
# reader do |blk,target|
|
1671
|
+
# # On reset the read trigger is 0.
|
1672
|
+
# rst = send(rst_name)
|
1673
|
+
# top_block.unshift do
|
1674
|
+
# # Initialize the address so that the next access is at address 0.
|
1675
|
+
# hif(rst==1) { abus_r <= 0 }
|
1676
|
+
# end
|
1677
|
+
# # Select the bank depending on the address.
|
1678
|
+
# hcase(abus_r / nbanks)
|
1679
|
+
# nbanks.times do |i|
|
1680
|
+
# hwhen(i) do
|
1681
|
+
# bank_brs[i].read(abus_r % nbanks,target) do
|
1682
|
+
# abus_r <= abus_r + 1
|
1683
|
+
# blk.call
|
1684
|
+
# end
|
1685
|
+
# end
|
1686
|
+
# end
|
1687
|
+
# end
|
1688
|
+
# end
|
1689
|
+
# # Write with increment
|
1690
|
+
# brancher(:winc) do
|
1691
|
+
# reader_output :abus_w
|
1692
|
+
# if br_rsts[:winc] then
|
1693
|
+
# rst_name = br_rsts[:winc].to_sym
|
1694
|
+
# else
|
1695
|
+
# rst_name = rst.name
|
1696
|
+
# writer_input rst_name
|
1697
|
+
# end
|
1698
|
+
# # Create the write branch for each bank.
|
1699
|
+
# bank_brs = banks.map do |bank|
|
1700
|
+
# bank.branch(:waddr).inner HDLRuby.uniq_name
|
1701
|
+
# end
|
1702
|
+
#
|
1703
|
+
# # Defines the read procedure at address +addr+
|
1704
|
+
# # using +target+ as target of access result.
|
1705
|
+
# writer do |blk,target|
|
1706
|
+
# # On reset the read trigger is 0.
|
1707
|
+
# rst = send(rst_name)
|
1708
|
+
# top_block.unshift do
|
1709
|
+
# # Initialize the address so that the next access is at address 0.
|
1710
|
+
# hif(rst==1) { abus_w <= 0 }
|
1711
|
+
# end
|
1712
|
+
# # Select the bank depending on the address.
|
1713
|
+
# hcase(abus_w / nbanks)
|
1714
|
+
# nbanks.times do |i|
|
1715
|
+
# hwhen(i) do
|
1716
|
+
# bank_brs[i].read(abus_w % nbanks,target) do
|
1717
|
+
# abus_w <= abus_w + 1
|
1718
|
+
# blk.call
|
1719
|
+
# end
|
1720
|
+
# end
|
1721
|
+
# end
|
1722
|
+
# end
|
1723
|
+
# end
|
1724
|
+
#
|
1725
|
+
# # The decrement branches.
|
1726
|
+
# # Read with decrement
|
1727
|
+
# brancher(:rdec) do
|
1728
|
+
# reader_output :abus_r
|
1729
|
+
# if br_rsts[:rdec] then
|
1730
|
+
# rst_name = br_rsts[:rdec].to_sym
|
1731
|
+
# else
|
1732
|
+
# rst_name = rst.name
|
1733
|
+
# reader_input rst_name
|
1734
|
+
# end
|
1735
|
+
#
|
1736
|
+
# # Defines the read procedure at address +addr+
|
1737
|
+
# # using +target+ as target of access result.
|
1738
|
+
# reader do |blk,target|
|
1739
|
+
# # On reset the read trigger is 0.
|
1740
|
+
# rst = send(rst_name)
|
1741
|
+
# top_block.unshift do
|
1742
|
+
# # Initialize the address so that the next access is at address 0.
|
1743
|
+
# hif(rst==1) { abus_r <= 0 }
|
1744
|
+
# end
|
1745
|
+
# # Select the bank depending on the address.
|
1746
|
+
# hcase(abus_r / nbanks)
|
1747
|
+
# nbanks.times do |i|
|
1748
|
+
# hwhen(i) do
|
1749
|
+
# banks[i].read(abus_r % nbanks,target) do
|
1750
|
+
# abus_r <= abus_r + 1
|
1751
|
+
# blk.call
|
1752
|
+
# end
|
1753
|
+
# end
|
1754
|
+
# end
|
1755
|
+
# end
|
1756
|
+
# end
|
1757
|
+
# # Write with decrement
|
1758
|
+
# brancher(:wdec) do
|
1759
|
+
# reader_output :abus_w
|
1760
|
+
# if br_rsts[:wdec] then
|
1761
|
+
# rst_name = br_rsts[:wdec].to_sym
|
1762
|
+
# else
|
1763
|
+
# rst_name = rst.name
|
1764
|
+
# writer_input rst_name
|
1765
|
+
# end
|
1766
|
+
#
|
1767
|
+
# # Defines the read procedure at address +addr+
|
1768
|
+
# # using +target+ as target of access result.
|
1769
|
+
# writer do |blk,target|
|
1770
|
+
# # On reset the read trigger is 0.
|
1771
|
+
# rst = send(rst_name)
|
1772
|
+
# top_block.unshift do
|
1773
|
+
# # Initialize the address so that the next access is at address 0.
|
1774
|
+
# hif(rst==1) { abus_w <= 0 }
|
1775
|
+
# end
|
1776
|
+
# # Select the bank depending on the address.
|
1777
|
+
# hcase(abus_w / nbanks)
|
1778
|
+
# nbanks.times do |i|
|
1779
|
+
# hwhen(i) do
|
1780
|
+
# banks[i].read(abus_w % nbanks,target) do
|
1781
|
+
# abus_w <= abus_w + 1
|
1782
|
+
# blk.call
|
1783
|
+
# end
|
1784
|
+
# end
|
1785
|
+
# end
|
1786
|
+
# end
|
1787
|
+
# end
|
1788
|
+
#
|
1789
|
+
# end
|