HDLRuby 2.3.6 → 2.4.8
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 +1 -0
- data/lib/HDLRuby/hdr_samples/bstr_bench.rb +14 -0
- data/lib/HDLRuby/hdr_samples/neg_arith_bench.rb +49 -0
- data/lib/HDLRuby/hdr_samples/with_fixpoint.rb +27 -0
- data/lib/HDLRuby/hdr_samples/with_linear.rb +3 -15
- data/lib/HDLRuby/hdr_samples/with_multi_channels.rb +300 -0
- data/lib/HDLRuby/hdrcc.rb +10 -1
- data/lib/HDLRuby/hruby_bstr.rb +7 -2
- data/lib/HDLRuby/hruby_high.rb +8 -0
- data/lib/HDLRuby/hruby_low.rb +107 -8
- data/lib/HDLRuby/hruby_low2c.rb +31 -9
- data/lib/HDLRuby/hruby_low_mutable.rb +90 -2
- data/lib/HDLRuby/hruby_low_resolve.rb +1 -0
- data/lib/HDLRuby/hruby_low_without_connection.rb +1 -0
- data/lib/HDLRuby/sim/hruby_sim.h +82 -39
- data/lib/HDLRuby/sim/hruby_sim_calc.c +89 -5
- data/lib/HDLRuby/sim/hruby_sim_core.c +32 -6
- data/lib/HDLRuby/sim/hruby_sim_vcd.c +380 -0
- data/lib/HDLRuby/sim/hruby_sim_vizualize.c +51 -12
- data/lib/HDLRuby/std/channel.rb +302 -60
- data/lib/HDLRuby/std/fixpoint.rb +10 -2
- data/lib/HDLRuby/std/linear.rb +33 -13
- data/lib/HDLRuby/std/memory.rb +12 -5
- data/lib/HDLRuby/version.rb +1 -1
- metadata +6 -2
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -325,6 +325,86 @@ module HDLRuby::High::Std
|
|
325
325
|
end
|
326
326
|
|
327
327
|
|
328
|
+
##
|
329
|
+
# Module giving the methods for accessing a channel instance.
|
330
|
+
module HchannelI
|
331
|
+
## Performs a read on the channel using +args+ and +ruby_block+
|
332
|
+
# as arguments.
|
333
|
+
# NOTE:
|
334
|
+
# * Will generate a port if not present.
|
335
|
+
# * Will generate an error if a read is tempted while the read
|
336
|
+
# port has been declared within another system.
|
337
|
+
def read(*args,&ruby_block)
|
338
|
+
# Is there a port to read?
|
339
|
+
unless self.read_port then
|
340
|
+
# No, generate a new one.
|
341
|
+
# Is it possible to be inout?
|
342
|
+
if self.inout? then
|
343
|
+
# Yes, create an inout port.
|
344
|
+
self.inout(HDLRuby.uniq_name)
|
345
|
+
else
|
346
|
+
# No, create an input port.
|
347
|
+
self.input(HDLRuby.uniq_name)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
# Ensure the read port is within current system.
|
351
|
+
unless self.read_port.scope.system != HDLRuby::High.cur_system then
|
352
|
+
raise "Cannot read from a port external of current system for channel " + self.name
|
353
|
+
end
|
354
|
+
# Performs the read.
|
355
|
+
self.read_port.read(*args,&ruby_block)
|
356
|
+
end
|
357
|
+
|
358
|
+
## Performs a write on the channel using +args+ and +ruby_block+
|
359
|
+
# as arguments.
|
360
|
+
# NOTE:
|
361
|
+
# * Will generate a port if not present.
|
362
|
+
# * Will generate an error if a read is tempted while the read
|
363
|
+
# port has been declared within another system.
|
364
|
+
def write(*args,&ruby_block)
|
365
|
+
# Is there a port to write?
|
366
|
+
unless self.write_port then
|
367
|
+
# No, generate a new one.
|
368
|
+
# Is it possible to be inout?
|
369
|
+
if self.inout? then
|
370
|
+
# Yes, create an inout port.
|
371
|
+
self.inout(HDLRuby.uniq_name)
|
372
|
+
else
|
373
|
+
# No, create an output port.
|
374
|
+
self.output(HDLRuby.uniq_name)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
# Ensure the write port is within current system.
|
378
|
+
unless self.write_port.scope.system != HDLRuby::High.cur_system then
|
379
|
+
raise "Cannot write from a port external of current system for channel " + self.name
|
380
|
+
end
|
381
|
+
# Performs the write.
|
382
|
+
self.write_port.write(*args,&ruby_block)
|
383
|
+
end
|
384
|
+
|
385
|
+
|
386
|
+
## Performs a reset on the channel using +args+ and +ruby_block+
|
387
|
+
# as arguments.
|
388
|
+
def reset(*args,&ruby_block)
|
389
|
+
# Gain access to the writer as local variable.
|
390
|
+
reseter_proc = @inout_reseter_proc
|
391
|
+
# # The context is the one of the writer.
|
392
|
+
# Execute the code generating the writer in context.
|
393
|
+
HDLRuby::High.space_push(@namespace)
|
394
|
+
HDLRuby::High.cur_block.open do
|
395
|
+
instance_exec(ruby_block,*args,&reseter_proc)
|
396
|
+
end
|
397
|
+
HDLRuby::High.space_pop
|
398
|
+
end
|
399
|
+
|
400
|
+
|
401
|
+
# Wrap with +args+ arguments.
|
402
|
+
def wrap(*args)
|
403
|
+
return ChannelB.new(self,*args)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
|
328
408
|
|
329
409
|
##
|
330
410
|
# Describes a high-level channel instance.
|
@@ -864,12 +944,12 @@ module HDLRuby::High::Std
|
|
864
944
|
# Ensure the port is not already existing.
|
865
945
|
if @read_port then
|
866
946
|
raise "Read port already declared for channel instance: " +
|
867
|
-
self.name
|
947
|
+
self.name.to_s
|
868
948
|
end
|
869
949
|
|
870
950
|
if @write_port then
|
871
951
|
raise "Write port already declared for channel instance: " +
|
872
|
-
self.name
|
952
|
+
self.name.to_s
|
873
953
|
end
|
874
954
|
|
875
955
|
# Access the ports
|
@@ -1006,76 +1086,238 @@ module HDLRuby::High::Std
|
|
1006
1086
|
# return chp
|
1007
1087
|
# end
|
1008
1088
|
|
1089
|
+
# Standard channel access is given is HchannelI module.
|
1090
|
+
include HchannelI
|
1009
1091
|
|
1010
1092
|
|
1011
|
-
## Performs a read on the channel using +args+ and +ruby_block+
|
1012
|
-
# as arguments.
|
1013
|
-
# NOTE:
|
1014
|
-
# * Will generate a port if not present.
|
1015
|
-
# * Will generate an error if a read is tempted while the read
|
1016
|
-
# port has been declared within another system.
|
1017
|
-
def read(*args,&ruby_block)
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1093
|
+
# ## Performs a read on the channel using +args+ and +ruby_block+
|
1094
|
+
# # as arguments.
|
1095
|
+
# # NOTE:
|
1096
|
+
# # * Will generate a port if not present.
|
1097
|
+
# # * Will generate an error if a read is tempted while the read
|
1098
|
+
# # port has been declared within another system.
|
1099
|
+
# def read(*args,&ruby_block)
|
1100
|
+
# # Is there a port to read?
|
1101
|
+
# unless self.read_port then
|
1102
|
+
# # No, generate a new one.
|
1103
|
+
# # Is it possible to be inout?
|
1104
|
+
# if self.inout? then
|
1105
|
+
# # Yes, create an inout port.
|
1106
|
+
# self.inout(HDLRuby.uniq_name)
|
1107
|
+
# else
|
1108
|
+
# # No, create an input port.
|
1109
|
+
# self.input(HDLRuby.uniq_name)
|
1110
|
+
# end
|
1111
|
+
# end
|
1112
|
+
# # Ensure the read port is within current system.
|
1113
|
+
# unless self.read_port.scope.system != HDLRuby::High.cur_system then
|
1114
|
+
# raise "Cannot read from a port external of current system for channel " + self.name
|
1115
|
+
# end
|
1116
|
+
# # Performs the read.
|
1117
|
+
# self.read_port.read(*args,&ruby_block)
|
1118
|
+
# end
|
1119
|
+
#
|
1120
|
+
# ## Performs a write on the channel using +args+ and +ruby_block+
|
1121
|
+
# # as arguments.
|
1122
|
+
# # NOTE:
|
1123
|
+
# # * Will generate a port if not present.
|
1124
|
+
# # * Will generate an error if a read is tempted while the read
|
1125
|
+
# # port has been declared within another system.
|
1126
|
+
# def write(*args,&ruby_block)
|
1127
|
+
# # Is there a port to write?
|
1128
|
+
# unless self.write_port then
|
1129
|
+
# # No, generate a new one.
|
1130
|
+
# # Is it possible to be inout?
|
1131
|
+
# if self.inout? then
|
1132
|
+
# # Yes, create an inout port.
|
1133
|
+
# self.inout(HDLRuby.uniq_name)
|
1134
|
+
# else
|
1135
|
+
# # No, create an output port.
|
1136
|
+
# self.output(HDLRuby.uniq_name)
|
1137
|
+
# end
|
1138
|
+
# end
|
1139
|
+
# # Ensure the write port is within current system.
|
1140
|
+
# unless self.write_port.scope.system != HDLRuby::High.cur_system then
|
1141
|
+
# raise "Cannot write from a port external of current system for channel " + self.name
|
1142
|
+
# end
|
1143
|
+
# # Performs the write.
|
1144
|
+
# self.write_port.write(*args,&ruby_block)
|
1145
|
+
# end
|
1146
|
+
#
|
1147
|
+
|
1148
|
+
# ## Performs a reset on the channel using +args+ and +ruby_block+
|
1149
|
+
# # as arguments.
|
1150
|
+
# def reset(*args,&ruby_block)
|
1151
|
+
# # Gain access to the writer as local variable.
|
1152
|
+
# reseter_proc = @inout_reseter_proc
|
1153
|
+
# # # The context is the one of the writer.
|
1154
|
+
# # Execute the code generating the writer in context.
|
1155
|
+
# HDLRuby::High.space_push(@namespace)
|
1156
|
+
# HDLRuby::High.cur_block.open do
|
1157
|
+
# instance_exec(ruby_block,*args,&reseter_proc)
|
1158
|
+
# end
|
1159
|
+
# HDLRuby::High.space_pop
|
1160
|
+
# end
|
1161
|
+
end
|
1162
|
+
|
1163
|
+
# Describes channel instance wrapper (Box) for fixing arugments.
|
1164
|
+
class ChannelB
|
1165
|
+
include HDLRuby::High::Hmissing
|
1166
|
+
include HchannelI
|
1167
|
+
|
1168
|
+
# Create a new channel box over +channelI+ channel instance using
|
1169
|
+
# +args+ for fixing the arguments as follows:
|
1170
|
+
# It can also be three lists for seperate read, write and access
|
1171
|
+
# procedures using named arguments as:
|
1172
|
+
# read: <read arguments>, write: <write arguments>,
|
1173
|
+
# access: <access arguments>
|
1174
|
+
def initialize(channelI,*args)
|
1175
|
+
# Ensure port is a channel port.
|
1176
|
+
unless channelI.is_a?(ChannelI) || channel.is_a?(ChannelB)
|
1177
|
+
raise "Invalid class for a channel instance: #{ch.class}"
|
1029
1178
|
end
|
1030
|
-
|
1031
|
-
|
1032
|
-
|
1179
|
+
@channelI = channelI
|
1180
|
+
# Process the arguments.
|
1181
|
+
if args.size == 1 && args[0].is_a?(Hash) then
|
1182
|
+
# Read, write and access are separated.
|
1183
|
+
@args_read = args[0][:read]
|
1184
|
+
@args_write = args[0][:write]
|
1185
|
+
@args_access = args[0][:access]
|
1186
|
+
else
|
1187
|
+
@args_read = args
|
1188
|
+
@args_write = args.clone
|
1189
|
+
@args_access = args.clone
|
1033
1190
|
end
|
1034
|
-
# Performs the read.
|
1035
|
-
self.read_port.read(*args,&ruby_block)
|
1036
1191
|
end
|
1192
|
+
|
1193
|
+
# Delegates to the boxed channel instance.
|
1194
|
+
|
1195
|
+
# The name of the channel instance.
|
1196
|
+
def name
|
1197
|
+
return @channelI.name
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
# The scope the channel has been created in.
|
1201
|
+
def scope
|
1202
|
+
return @channelI.scope
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
# The namespace associated with the current execution when
|
1206
|
+
# building a channel.
|
1207
|
+
def namespace
|
1208
|
+
return @channelI.namespace
|
1209
|
+
end
|
1210
|
+
|
1211
|
+
# The read port if any.
|
1212
|
+
def read_port
|
1213
|
+
return @read_port
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
# The write port if any.
|
1217
|
+
def write_port
|
1218
|
+
return @write_port
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
# Methods used on the channel outside its definition.
|
1037
1222
|
|
1038
|
-
|
1039
|
-
#
|
1040
|
-
#
|
1041
|
-
# *
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1223
|
+
# Gets branch channel +name+.
|
1224
|
+
# NOTE:
|
1225
|
+
# * +name+ can be of any type on purpose.
|
1226
|
+
# * The wrapping arguments are not transmitted to the branch.
|
1227
|
+
def branch(name,*args)
|
1228
|
+
return @channelI.branch(name,*args)
|
1229
|
+
end
|
1230
|
+
|
1231
|
+
## Tells if the channel support inout port.
|
1232
|
+
def inout?
|
1233
|
+
return @channelI.inout?
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
|
1237
|
+
# Reader, writer and accesser side.
|
1238
|
+
|
1239
|
+
## Declares the reader port as and assigned them to +name+.
|
1240
|
+
def input(name = nil)
|
1241
|
+
# Ensure name is a symbol.
|
1242
|
+
name = HDLRuby.uniq_name unless name
|
1243
|
+
name = name.to_sym
|
1244
|
+
# Ensure the port is not already existing.
|
1245
|
+
if @read_port then
|
1246
|
+
raise "Read port already declared for channel instance: " +
|
1247
|
+
self.name
|
1056
1248
|
end
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1249
|
+
|
1250
|
+
# Create a read port for the encaspulted channel.
|
1251
|
+
real_port = @channelI.read_port
|
1252
|
+
real_port = @channelI.input unless real_port
|
1253
|
+
|
1254
|
+
# Wrap it to a new port using.
|
1255
|
+
chp = real_port.wrap(read: @args_read)
|
1256
|
+
|
1257
|
+
HDLRuby::High.space_reg(name) { chp }
|
1258
|
+
# Save the port in the channe to avoid conflicting declaration.
|
1259
|
+
@read_port = chp
|
1260
|
+
return chp
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
## Declares the ports for the writer and assigned them to +name+.
|
1264
|
+
def output(name = nil)
|
1265
|
+
# Ensure name is a symbol.
|
1266
|
+
name = HDLRuby.uniq_name unless name
|
1267
|
+
name = name.to_sym
|
1268
|
+
# Ensure the port is not already existing.
|
1269
|
+
if @write_port then
|
1270
|
+
raise "Read port already declared for channel instance: " +
|
1271
|
+
self.name
|
1060
1272
|
end
|
1061
|
-
|
1062
|
-
|
1273
|
+
|
1274
|
+
# Create a write port for the encaspulted channel.
|
1275
|
+
real_port = @channelI.write_port
|
1276
|
+
real_port = @channelI.output unless real_port
|
1277
|
+
|
1278
|
+
# Wrap it to a new port using.
|
1279
|
+
chp = real_port.wrap(write: @args_write)
|
1280
|
+
|
1281
|
+
HDLRuby::High.space_reg(name) { chp }
|
1282
|
+
# Save the port in the channe to avoid conflicting declaration.
|
1283
|
+
@write_port = chp
|
1284
|
+
return chp
|
1063
1285
|
end
|
1064
|
-
|
1065
1286
|
|
1066
|
-
|
1067
|
-
|
1068
|
-
def
|
1069
|
-
#
|
1070
|
-
|
1071
|
-
|
1072
|
-
#
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1287
|
+
|
1288
|
+
## Declares the accesser port and assigned them to +name+.
|
1289
|
+
def inout(name = nil)
|
1290
|
+
# Ensure name is a symbol.
|
1291
|
+
name = HDLRuby.uniq_name unless name
|
1292
|
+
name = name.to_sym
|
1293
|
+
# Ensure the port is not already existing.
|
1294
|
+
if @read_port then
|
1295
|
+
raise "Read port already declared for channel instance: " +
|
1296
|
+
self.name
|
1076
1297
|
end
|
1077
|
-
|
1298
|
+
if @write_port then
|
1299
|
+
raise "Write port already declared for channel instance: " +
|
1300
|
+
self.name
|
1301
|
+
end
|
1302
|
+
|
1303
|
+
# Create a write port for the encaspulted channel.
|
1304
|
+
if @channelI.read_port == @channelI.write_port then
|
1305
|
+
real_port = @channelI.read_port
|
1306
|
+
real_port = @channelI.inout unless real_port
|
1307
|
+
else
|
1308
|
+
raise "Inout port not supported for channel #{@channelI}"
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
# Wrap it to a new port using.
|
1312
|
+
chp = real_port.wrap(read: @args_read, write: @args_write)
|
1313
|
+
|
1314
|
+
HDLRuby::High.space_reg(name) { chp }
|
1315
|
+
# Save the port in the channe to avoid conflicting declaration.
|
1316
|
+
@write_port = chp
|
1317
|
+
@read_port = chp
|
1318
|
+
return chp
|
1078
1319
|
end
|
1320
|
+
|
1079
1321
|
end
|
1080
1322
|
|
1081
1323
|
|
data/lib/HDLRuby/std/fixpoint.rb
CHANGED
@@ -52,10 +52,18 @@ module HDLRuby::High::Std
|
|
52
52
|
end
|
53
53
|
# Redefine the multiplication and division for fixed point.
|
54
54
|
typ.define_operator(:*) do |left,right|
|
55
|
-
(
|
55
|
+
if (typ.signed?) then
|
56
|
+
(left.as(signed[isize+fsize*2])*right) >> fsize
|
57
|
+
else
|
58
|
+
(left.as([isize+fsize*2])*right) >> fsize
|
59
|
+
end
|
56
60
|
end
|
57
61
|
typ.define_operator(:/) do |left,right|
|
58
|
-
(
|
62
|
+
if (typ.signed?) then
|
63
|
+
(left.as(signed[isize+fsize*2]) << fsize) / right
|
64
|
+
else
|
65
|
+
(left.as([isize+fsize*2]) << fsize) / right
|
66
|
+
end
|
59
67
|
end
|
60
68
|
typ
|
61
69
|
end
|
data/lib/HDLRuby/std/linear.rb
CHANGED
@@ -209,37 +209,57 @@ module HDLRuby::High::Std
|
|
209
209
|
# lv and rv are valid.
|
210
210
|
lvoks = lefts.each_with_index.map { |left,i| inner :"lvok#{i}" }
|
211
211
|
inner :rvok
|
212
|
+
woks = lefts.each_with_index.map { |left,i| inner :"wok#{i}" }
|
212
213
|
# Run flag
|
213
214
|
inner :run
|
214
215
|
par(ev) do
|
215
216
|
ack <= 0
|
216
217
|
run <= 0
|
218
|
+
hif(~run) do
|
219
|
+
rvok <= 0
|
220
|
+
lefts.each_with_index do |left,i|
|
221
|
+
lvoks[i] <= 0
|
222
|
+
# avs[i] <= 0
|
223
|
+
woks[i] <= 0
|
224
|
+
end
|
225
|
+
end
|
217
226
|
hif(req | run) do
|
218
227
|
run <= 1
|
219
228
|
# Computation request.
|
220
|
-
right.read(rv) { rvok <= 1 }
|
229
|
+
hif(~rvok) { right.read(rv) { rvok <= 1 } }
|
221
230
|
lefts.each_with_index do |left,i|
|
222
|
-
left.read(lvs[i]) { lvoks[i] <= 1 }
|
231
|
+
hif(~lvoks[i]) { left.read(lvs[i]) { lvoks[i] <= 1 } }
|
223
232
|
# accs[i].read(avs[i])
|
224
|
-
hif(lvoks[i] & rvok) do
|
233
|
+
hif(lvoks[i] & rvok & ~woks[i]) do
|
225
234
|
ack <= 1
|
226
235
|
run <= 0
|
227
|
-
# accs[i].write(add.(avs[i],mul.(lvs[i],rv)))
|
228
236
|
seq do
|
229
237
|
avs[i] <= add.(avs[i],mul.(lvs[i],rv))
|
230
|
-
accs[i].write(avs[i])
|
238
|
+
accs[i].write(avs[i]) do
|
239
|
+
woks[i] <= 1
|
240
|
+
# seq do
|
241
|
+
# lvoks[i] <= 0
|
242
|
+
# rvok <= lvoks.reduce(:|)
|
243
|
+
# end
|
244
|
+
end
|
231
245
|
end
|
232
246
|
end
|
247
|
+
hif (woks.reduce(:&)) do
|
248
|
+
woks.each { |wok| wok <= 0 }
|
249
|
+
lvoks.each { | lvok| lvok <=0 }
|
250
|
+
rvok <= 0
|
251
|
+
end
|
233
252
|
end
|
234
253
|
end
|
235
|
-
helse
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
end
|
254
|
+
helse { avs.each {|av| av <= 0 } }
|
255
|
+
# helse do
|
256
|
+
# rvok <= 0
|
257
|
+
# lefts.each_with_index do |left,i|
|
258
|
+
# lvoks[i] <= 0
|
259
|
+
# # accs[i].write(0)
|
260
|
+
# avs[i] <= 0
|
261
|
+
# end
|
262
|
+
# end
|
243
263
|
end
|
244
264
|
end
|
245
265
|
|