HDLRuby 2.11.2 → 2.11.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 +6 -2
- data/ext/hruby_sim/hruby_rcsim_build.c +325 -73
- data/ext/hruby_sim/hruby_sim.h +11 -1
- data/ext/hruby_sim/hruby_sim_calc.c +11 -8
- data/ext/hruby_sim/hruby_sim_core.c +8 -6
- data/ext/hruby_sim/hruby_sim_tree_calc.c +14 -0
- data/ext/hruby_sim/hruby_value_pool.c +6 -4
- data/lib/HDLRuby/hdr_samples/repeat_bench.rb +48 -0
- data/lib/HDLRuby/hruby_high.rb +11 -6
- data/lib/HDLRuby/hruby_low.rb +27 -17
- data/lib/HDLRuby/hruby_low2c.rb +26 -7
- data/lib/HDLRuby/hruby_rcsim.rb +119 -74
- data/lib/HDLRuby/hruby_rsim.rb +10 -1
- data/lib/HDLRuby/hruby_rsim_vcd.rb +15 -0
- data/lib/HDLRuby/hruby_verilog.rb +71 -58
- data/lib/HDLRuby/version.rb +1 -1
- metadata +3 -2
data/ext/hruby_sim/hruby_sim.h
CHANGED
@@ -28,6 +28,7 @@ typedef struct PrintS_ PrintS;
|
|
28
28
|
typedef struct HIfS_ HIfS;
|
29
29
|
typedef struct HCaseS_ HCaseS;
|
30
30
|
typedef struct TimeWaitS_ TimeWaitS;
|
31
|
+
typedef struct TimeRepeatS_ TimeRepeatS;
|
31
32
|
typedef struct TimeTerminateS_ TimeTerminateS;
|
32
33
|
typedef struct ExpressionS_ ExpressionS;
|
33
34
|
typedef struct UnaryS_ UnaryS;
|
@@ -63,6 +64,7 @@ typedef struct PrintS_* Print;
|
|
63
64
|
typedef struct HIfS_* HIf;
|
64
65
|
typedef struct HCaseS_* HCase;
|
65
66
|
typedef struct TimeWaitS_* TimeWait;
|
67
|
+
typedef struct TimeRepeatS_* TimeRepeat;
|
66
68
|
typedef struct TimeTerminateS_* TimeTerminate;
|
67
69
|
typedef struct ExpressionS_* Expression;
|
68
70
|
typedef struct UnaryS_* Unary;
|
@@ -89,7 +91,8 @@ typedef enum {
|
|
89
91
|
#endif
|
90
92
|
OBJECT, SYSTEMT, SIGNALI, SCOPE, BEHAVIOR, SYSTEMI, CODE, BLOCK, EVENT,
|
91
93
|
#ifdef RCSIM
|
92
|
-
/* Statements */ TRANSMIT, PRINT, HIF, HCASE,
|
94
|
+
/* Statements */ TRANSMIT, PRINT, HIF, HCASE,
|
95
|
+
TIME_WAIT, TIME_REPEAT, TIME_TERMINATE,
|
93
96
|
/* Expressions */ UNARY, BINARY, SELECT, CONCAT, CAST,
|
94
97
|
/* References */ REF_OBJECT, REF_INDEX, REF_RANGE, REF_CONCAT,
|
95
98
|
/* Non-hardware*/ STRINGE,
|
@@ -670,6 +673,13 @@ typedef struct TimeWaitS_ {
|
|
670
673
|
unsigned long long delay; /* The delay to wait in pico seconds. */
|
671
674
|
} TimeWaitS;
|
672
675
|
|
676
|
+
/** The C model of a time repeat statement. */
|
677
|
+
typedef struct TimeRepeatS_ {
|
678
|
+
Kind kind; /* The kind of object. */
|
679
|
+
long long number; /* The number of interations, negative means infinity. */
|
680
|
+
Statement statement;/* The statement to execute in loop. */
|
681
|
+
} TimeRepeatS;
|
682
|
+
|
673
683
|
/** The C model of a time terminate statement. */
|
674
684
|
typedef struct TimeTerminateS_ {
|
675
685
|
Kind kind; /* The kind of object. */
|
@@ -5,9 +5,9 @@
|
|
5
5
|
#include <limits.h>
|
6
6
|
#include "hruby_sim.h"
|
7
7
|
|
8
|
-
#ifndef alloca
|
9
|
-
#define alloca(x) __builtin_alloca(x)
|
10
|
-
#endif
|
8
|
+
// #ifndef alloca
|
9
|
+
// #define alloca(x) __builtin_alloca(x)
|
10
|
+
// #endif
|
11
11
|
|
12
12
|
|
13
13
|
/**
|
@@ -147,7 +147,7 @@ Type get_type_signed() {
|
|
147
147
|
* @number the number of elements */
|
148
148
|
Type make_type_vector(Type base, unsigned long long number) {
|
149
149
|
/* Create the type. */
|
150
|
-
Type type = calloc(sizeof(TypeS)
|
150
|
+
Type type = calloc(1,sizeof(TypeS));
|
151
151
|
type->base = type_width(base);
|
152
152
|
type->number = number;
|
153
153
|
type->flags = base->flags;
|
@@ -201,7 +201,7 @@ Value make_value(Type type, int numeric) {
|
|
201
201
|
/* Compute the size in words of the data contained in the value. */
|
202
202
|
unsigned long long width = type_width(type);
|
203
203
|
/* Allocate the value. */
|
204
|
-
Value res = calloc(sizeof(ValueS)
|
204
|
+
Value res = calloc(1,sizeof(ValueS));
|
205
205
|
/* Allocates the data of the value. */
|
206
206
|
if (!numeric) {
|
207
207
|
/* Allocate the bit string and fill it with u (undefined) by default. */
|
@@ -232,7 +232,7 @@ void resize_value(Value value, unsigned long long size) {
|
|
232
232
|
/* Free the former data. */
|
233
233
|
free(value->data_str);
|
234
234
|
/* Reallocate it. */
|
235
|
-
value->data_str = calloc(sizeof(char)
|
235
|
+
value->data_str = calloc(size*2,sizeof(char));
|
236
236
|
/* Update the size. */
|
237
237
|
value->capacity = size*2;
|
238
238
|
}
|
@@ -2977,12 +2977,15 @@ Value concat_valueP(unsigned int num, int dir, Value dst, Value* values) {
|
|
2977
2977
|
}
|
2978
2978
|
Value concat_valueV(unsigned int num, int dir, Value dst, va_list args) {
|
2979
2979
|
unsigned int i;
|
2980
|
-
Value* values = alloca(num*sizeof(Value)); /* The values to concatenate. */
|
2980
|
+
// Value* values = alloca(num*sizeof(Value)); /* The values to concatenate. */
|
2981
|
+
Value* values = calloc(num,sizeof(Value)); /* The values to concatenate. */
|
2981
2982
|
/* Copy the arguments to values for easier processing. */
|
2982
2983
|
for(i=0; i<num; ++i) {
|
2983
2984
|
values[i] = va_arg(args,Value);
|
2984
2985
|
}
|
2985
|
-
|
2986
|
+
Value res = concat_valueP(num,dir,dst,values);
|
2987
|
+
free(values);
|
2988
|
+
return res;
|
2986
2989
|
}
|
2987
2990
|
Value concat_value(unsigned int num, int dir, Value dst, ...) {
|
2988
2991
|
va_list args;
|
@@ -72,11 +72,12 @@ void register_timed_behavior(Behavior behavior) {
|
|
72
72
|
if (cap_timed_behaviors == 0) {
|
73
73
|
/* Need to create the array containing the timed behaviors. */
|
74
74
|
cap_timed_behaviors = 5;
|
75
|
-
timed_behaviors = calloc(sizeof(Behavior)
|
75
|
+
timed_behaviors = calloc(cap_timed_behaviors,sizeof(Behavior));
|
76
76
|
} else {
|
77
77
|
/* Need to increase the capacity. */
|
78
|
-
Behavior* behaviors = calloc(sizeof(Behavior)
|
79
|
-
memcpy(behaviors,timed_behaviors,sizeof(Behavior)*cap_timed_behaviors);
|
78
|
+
Behavior* behaviors = calloc(cap_timed_behaviors*2,sizeof(Behavior));
|
79
|
+
// memcpy(behaviors,timed_behaviors,sizeof(Behavior)*cap_timed_behaviors);
|
80
|
+
memcpy(behaviors,timed_behaviors,sizeof(Behavior[cap_timed_behaviors]));
|
80
81
|
timed_behaviors = behaviors;
|
81
82
|
cap_timed_behaviors *= 2;
|
82
83
|
}
|
@@ -93,11 +94,12 @@ void register_signal(SignalI signal) {
|
|
93
94
|
if (cap_all_signals == 0) {
|
94
95
|
/* Need to create the array containing the timed behaviors. */
|
95
96
|
cap_all_signals = 100;
|
96
|
-
all_signals = calloc(sizeof(SignalI)
|
97
|
+
all_signals = calloc(cap_all_signals,sizeof(SignalI));
|
97
98
|
} else {
|
98
99
|
/* Need to increase the capacity. */
|
99
|
-
SignalI* new_signals = calloc(sizeof(SignalI)
|
100
|
-
memcpy(new_signals,all_signals,sizeof(SignalI)*cap_all_signals);
|
100
|
+
SignalI* new_signals = calloc(cap_all_signals*2,sizeof(SignalI));
|
101
|
+
// memcpy(new_signals,all_signals,sizeof(SignalI)*cap_all_signals);
|
102
|
+
memcpy(new_signals,all_signals,sizeof(SignalI[cap_all_signals]));
|
101
103
|
cap_all_signals *= 2;
|
102
104
|
all_signals=new_signals;
|
103
105
|
}
|
@@ -358,6 +358,20 @@ void execute_statement(Statement stmnt, int mode, Behavior behavior) {
|
|
358
358
|
hw_wait(delay,behavior);
|
359
359
|
break;
|
360
360
|
}
|
361
|
+
case TIME_REPEAT:
|
362
|
+
{
|
363
|
+
TimeRepeat rep = (TimeRepeat)stmnt;
|
364
|
+
if (rep->number>=0) {
|
365
|
+
for(long long i=0; i<rep->number; ++i) {
|
366
|
+
execute_statement(rep->statement,mode,behavior);
|
367
|
+
}
|
368
|
+
} else {
|
369
|
+
for(;;) {
|
370
|
+
execute_statement(rep->statement,mode,behavior);
|
371
|
+
}
|
372
|
+
}
|
373
|
+
break;
|
374
|
+
}
|
361
375
|
case BLOCK:
|
362
376
|
{
|
363
377
|
Block block = (Block)stmnt;
|
@@ -20,9 +20,10 @@ Value get_value() {
|
|
20
20
|
if (pool_cap == 0) {
|
21
21
|
/* First allocation. */
|
22
22
|
pool_cap = 16;
|
23
|
-
pool_values = (Value*)malloc(pool_cap*sizeof(Value));
|
23
|
+
// pool_values = (Value*)malloc(pool_cap*sizeof(Value));
|
24
|
+
pool_values = (Value*)calloc(pool_cap,sizeof(Value));
|
24
25
|
/* Allocate the new values. */
|
25
|
-
ValueS* new_values = (ValueS*)calloc(sizeof(ValueS)
|
26
|
+
ValueS* new_values = (ValueS*)calloc(pool_cap,sizeof(ValueS));
|
26
27
|
/* Assign them to the pool. */
|
27
28
|
unsigned int i;
|
28
29
|
for(i=0; i<pool_cap; ++i) {
|
@@ -32,7 +33,8 @@ Value get_value() {
|
|
32
33
|
else if (pool_pos == pool_cap) {
|
33
34
|
/* Need to increase the pool capacity. */
|
34
35
|
pool_cap = pool_cap * 2;
|
35
|
-
pool_values = (Value*)realloc(pool_values,pool_cap*sizeof(Value));
|
36
|
+
// pool_values = (Value*)realloc(pool_values,pool_cap*sizeof(Value));
|
37
|
+
pool_values = (Value*)realloc(pool_values,sizeof(Value[pool_cap]));
|
36
38
|
if (pool_values == NULL) {
|
37
39
|
perror("Internal error with the pool of values.");
|
38
40
|
exit(1);
|
@@ -40,7 +42,7 @@ Value get_value() {
|
|
40
42
|
/* Allocate the new values. */
|
41
43
|
/* Note: now pool_pos is the old pool_cap and is also the number
|
42
44
|
* of new values to allocate. */
|
43
|
-
ValueS* new_values = (ValueS*)calloc(sizeof(ValueS)
|
45
|
+
ValueS* new_values = (ValueS*)calloc(pool_pos,sizeof(ValueS));
|
44
46
|
/* Assign them to the pool. */
|
45
47
|
unsigned int i;
|
46
48
|
for(i=0; i<pool_pos; ++i) {
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# A simple D-FF
|
2
|
+
system :dff do
|
3
|
+
input :d, :clk, :rst
|
4
|
+
output :q
|
5
|
+
|
6
|
+
(q <= d & ~rst).at(clk.posedge)
|
7
|
+
end
|
8
|
+
|
9
|
+
# A benchmark for the dff using repeat.
|
10
|
+
system :dff_bench do
|
11
|
+
inner :d, :clk, :rst
|
12
|
+
inner :q
|
13
|
+
|
14
|
+
dff(:my_dff).(d,clk,rst,q)
|
15
|
+
|
16
|
+
timed do
|
17
|
+
clk <= 0
|
18
|
+
rst <= 0
|
19
|
+
d <= _z
|
20
|
+
!10.ns
|
21
|
+
clk <= 1
|
22
|
+
rst <= 0
|
23
|
+
d <= _z
|
24
|
+
!10.ns
|
25
|
+
clk <= 0
|
26
|
+
rst <= 1
|
27
|
+
d <= _z
|
28
|
+
!10.ns
|
29
|
+
clk <= 1
|
30
|
+
rst <= 1
|
31
|
+
d <= _z
|
32
|
+
!10.ns
|
33
|
+
clk <= 0
|
34
|
+
rst <= 0
|
35
|
+
d <= 1
|
36
|
+
!10.ns
|
37
|
+
clk <= 1
|
38
|
+
rst <= 0
|
39
|
+
!10.ns
|
40
|
+
repeat(100) do
|
41
|
+
clk <= 0
|
42
|
+
d <= ~d
|
43
|
+
!10.ns
|
44
|
+
clk <= 1
|
45
|
+
!10.ns
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/HDLRuby/hruby_high.rb
CHANGED
@@ -2682,10 +2682,10 @@ module HDLRuby::High
|
|
2682
2682
|
|
2683
2683
|
# Converts the repeat statement to HDLRuby::Low.
|
2684
2684
|
def to_low
|
2685
|
-
#
|
2685
|
+
# timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.statement.to_low,
|
2686
2686
|
# self.delay.to_low)
|
2687
|
-
timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.
|
2688
|
-
|
2687
|
+
timeRepeatL = HDLRuby::Low::TimeRepeat.new(self.number,
|
2688
|
+
self.statement.to_low)
|
2689
2689
|
# # For debugging: set the source high object
|
2690
2690
|
# timeRepeatL.properties[:low2high] = self.hdr_id
|
2691
2691
|
# self.properties[:high2low] = timeRepeatL
|
@@ -4233,15 +4233,20 @@ module HDLRuby::High
|
|
4233
4233
|
self.add_statement(TimeWait.new(delay))
|
4234
4234
|
end
|
4235
4235
|
|
4236
|
-
# Adds a loop until +delay+ statement in the block in +mode+ whose
|
4236
|
+
# # Adds a loop until +delay+ statement in the block in +mode+ whose
|
4237
|
+
# # loop content is built using +ruby_block+.
|
4238
|
+
# def repeat(delay, mode = nil, &ruby_block)
|
4239
|
+
# Adds a +number+ times loop statement in the block in +mode+ whose
|
4237
4240
|
# loop content is built using +ruby_block+.
|
4238
|
-
|
4241
|
+
# NOTE: if +number+ is negative, the number of iteration is infinite.
|
4242
|
+
def repeat(number = -1, mode = nil, &ruby_block)
|
4239
4243
|
# Ensure there is a block.
|
4240
4244
|
ruby_block = proc {} unless block_given?
|
4241
4245
|
# Build the content block.
|
4242
4246
|
content = High.make_block(mode,&ruby_block)
|
4243
4247
|
# Create and add the statement.
|
4244
|
-
self.add_statement(TimeRepeat.new(content,delay))
|
4248
|
+
# self.add_statement(TimeRepeat.new(content,delay))
|
4249
|
+
self.add_statement(TimeRepeat.new(number,content))
|
4245
4250
|
end
|
4246
4251
|
|
4247
4252
|
# Converts the time block to HDLRuby::Low.
|
data/lib/HDLRuby/hruby_low.rb
CHANGED
@@ -4042,15 +4042,20 @@ module HDLRuby::Low
|
|
4042
4042
|
##
|
4043
4043
|
# Describes a timed loop statement: not synthesizable!
|
4044
4044
|
class TimeRepeat < Statement
|
4045
|
-
# The delay until the loop is repeated
|
4046
|
-
attr_reader :delay
|
4045
|
+
# # The delay until the loop is repeated
|
4046
|
+
# attr_reader :delay
|
4047
|
+
# The number of interrations.
|
4048
|
+
attr_reader :number
|
4047
4049
|
|
4048
4050
|
# The statement to execute.
|
4049
4051
|
attr_reader :statement
|
4050
4052
|
|
4051
|
-
# Creates a new timed loop statement execute in a loop +statement+ until
|
4052
|
-
# +delay+ has passed.
|
4053
|
-
def initialize(statement,delay)
|
4053
|
+
# # Creates a new timed loop statement execute in a loop +statement+ until
|
4054
|
+
# # +delay+ has passed.
|
4055
|
+
# def initialize(statement,delay)
|
4056
|
+
# Creates a new timed loop statement execute in a loop +statement+
|
4057
|
+
# +number+ times (negative means inifinity).
|
4058
|
+
def initialize(number,statement)
|
4054
4059
|
# Check and set the statement.
|
4055
4060
|
unless statement.is_a?(Statement)
|
4056
4061
|
raise AnyError,
|
@@ -4061,13 +4066,15 @@ module HDLRuby::Low
|
|
4061
4066
|
# And set its parent.
|
4062
4067
|
statement.parent = self
|
4063
4068
|
|
4064
|
-
# Check and set the delay.
|
4065
|
-
unless delay.is_a?(Delay)
|
4066
|
-
|
4067
|
-
end
|
4068
|
-
@delay = delay
|
4069
|
-
#
|
4070
|
-
|
4069
|
+
# # Check and set the delay.
|
4070
|
+
# unless delay.is_a?(Delay)
|
4071
|
+
# raise AnyError, "Invalid class for a delay: #{delay.class}."
|
4072
|
+
# end
|
4073
|
+
# @delay = delay
|
4074
|
+
# Check and set the number.
|
4075
|
+
@number = number.to_i
|
4076
|
+
# # And set its parent.
|
4077
|
+
# delay.parent = self
|
4071
4078
|
end
|
4072
4079
|
|
4073
4080
|
# Iterates over each object deeply.
|
@@ -4080,26 +4087,29 @@ module HDLRuby::Low
|
|
4080
4087
|
ruby_block.call(self)
|
4081
4088
|
# Then apply on the statement.
|
4082
4089
|
self.statement.each_deep(&ruby_block)
|
4083
|
-
# Then apply on the delay.
|
4084
|
-
self.delay.each_deep(&ruby_block)
|
4090
|
+
# # Then apply on the delay.
|
4091
|
+
# self.delay.each_deep(&ruby_block)
|
4085
4092
|
end
|
4086
4093
|
|
4087
4094
|
# Comparison for hash: structural comparison.
|
4088
4095
|
def eql?(obj)
|
4089
4096
|
return false unless obj.is_a?(TimeRepeat)
|
4090
|
-
return false unless @delay.eql?(obj.delay)
|
4097
|
+
# return false unless @delay.eql?(obj.delay)
|
4098
|
+
return false unless @number.eql?(obj.number)
|
4091
4099
|
return false unless @statement.eql?(obj.statement)
|
4092
4100
|
return true
|
4093
4101
|
end
|
4094
4102
|
|
4095
4103
|
# Hash function.
|
4096
4104
|
def hash
|
4097
|
-
return [@delay,@statement].hash
|
4105
|
+
# return [@delay,@statement].hash
|
4106
|
+
return [@number,@statement].hash
|
4098
4107
|
end
|
4099
4108
|
|
4100
4109
|
# Clones the TimeRepeat (deeply)
|
4101
4110
|
def clone
|
4102
|
-
return TimeRepeat.new(@statement.clone,@delay.clone)
|
4111
|
+
# return TimeRepeat.new(@statement.clone,@delay.clone)
|
4112
|
+
return TimeRepeat.new(@statement.clone,@number)
|
4103
4113
|
end
|
4104
4114
|
|
4105
4115
|
# Iterates over the expression children if any.
|
data/lib/HDLRuby/hruby_low2c.rb
CHANGED
@@ -1803,20 +1803,39 @@ module HDLRuby::Low
|
|
1803
1803
|
## Extends the TimeRepeat class with generation of C text.
|
1804
1804
|
class TimeRepeat
|
1805
1805
|
|
1806
|
+
# # Generates the C text of the equivalent HDLRuby code.
|
1807
|
+
# # +level+ is the hierachical level of the object.
|
1808
|
+
# # def to_c(level = 0)
|
1809
|
+
# def to_c(res,level = 0)
|
1810
|
+
# # The resulting string.
|
1811
|
+
# # res = " " * level*3
|
1812
|
+
# res << " " * level*3
|
1813
|
+
# # Generate an infinite loop executing the block and waiting.
|
1814
|
+
# res << "for(;;) {\n"
|
1815
|
+
# # res << "#{self.statement.to_c(level+1)}\n"
|
1816
|
+
# self.statement.to_c(res,level+1)
|
1817
|
+
# res << "\n"
|
1818
|
+
# res << " " * (level+1)*3
|
1819
|
+
# res << Low2C.wait_code(self,level)
|
1820
|
+
# # Return the resulting string.
|
1821
|
+
# return res
|
1822
|
+
# end
|
1823
|
+
|
1806
1824
|
# Generates the C text of the equivalent HDLRuby code.
|
1807
1825
|
# +level+ is the hierachical level of the object.
|
1808
1826
|
# def to_c(level = 0)
|
1809
1827
|
def to_c(res,level = 0)
|
1810
1828
|
# The resulting string.
|
1811
|
-
# res = " " * level*3
|
1812
1829
|
res << " " * level*3
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1830
|
+
if (number < 0) then
|
1831
|
+
# Generate an infinite loop executing the block and waiting.
|
1832
|
+
res << "for(;;) {\n"
|
1833
|
+
else
|
1834
|
+
# Generate a finite loop.
|
1835
|
+
res << "for(long long i = 0; i<#{self.number}; ++i) {\n"
|
1836
|
+
end
|
1816
1837
|
self.statement.to_c(res,level+1)
|
1817
|
-
res << "\n"
|
1818
|
-
res << " " * (level+1)*3
|
1819
|
-
res << Low2C.wait_code(self,level)
|
1838
|
+
res << " " * level*3 << "}\n"
|
1820
1839
|
# Return the resulting string.
|
1821
1840
|
return res
|
1822
1841
|
end
|