HDLRuby 2.2.17 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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/sim/hruby_sim.h
CHANGED
@@ -157,6 +157,13 @@ extern Value mul_value(Value src0, Value src1, Value dst);
|
|
157
157
|
* @return dst */
|
158
158
|
extern Value div_value(Value src0, Value src1, Value dst);
|
159
159
|
|
160
|
+
/** Computes the modulo of two general values.
|
161
|
+
* @param src0 the first source value of the addition
|
162
|
+
* @param src1 the second source value of the addition
|
163
|
+
* @param dst the destination value
|
164
|
+
* @return dst */
|
165
|
+
extern Value mod_value(Value src0, Value src1, Value dst);
|
166
|
+
|
160
167
|
/** Computes the not of a value.
|
161
168
|
* @param src the source value of the not
|
162
169
|
* @param dst the destination value
|
@@ -605,14 +612,18 @@ extern Value read_range(Value value, long long first, long long last,
|
|
605
612
|
* @param src the source value
|
606
613
|
* @param first the first index of the range
|
607
614
|
* @param last the last index of the range
|
615
|
+
* @param base the type of the elements
|
608
616
|
* @param dst the destination value
|
609
617
|
* @return dst */
|
610
|
-
extern Value write_range(Value src, long long first, long long last,
|
618
|
+
extern Value write_range(Value src, long long first, long long last,
|
619
|
+
Type base, Value dst);
|
611
620
|
|
612
621
|
/** Writes to a range within a value but without overwrite with Z.
|
613
622
|
* @param src the source value
|
614
623
|
* @param first the first index of the range
|
615
624
|
* @param last the last index of the range
|
625
|
+
* @param base the type of the elements
|
616
626
|
* @param dst the destination value
|
617
627
|
* @return dst */
|
618
|
-
extern Value write_range_no_z(Value src, long long first, long long last,
|
628
|
+
extern Value write_range_no_z(Value src, long long first, long long last,
|
629
|
+
Type base, Value dst);
|
@@ -397,6 +397,9 @@ static Value set_undefined_bitstring(Value dst) {
|
|
397
397
|
|
398
398
|
/* set the type and size of the destination. */
|
399
399
|
dst->numeric = 0;
|
400
|
+
/* Ensures the buffer of dst has the write size (in cas it was a fromer
|
401
|
+
* numeric for example). */
|
402
|
+
resize_value(dst,width);
|
400
403
|
|
401
404
|
/* Get access to the destination data. */
|
402
405
|
char* dst_data = dst->data_str;
|
@@ -604,7 +607,7 @@ static Value mul_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
|
604
607
|
dst->type = src0->type;
|
605
608
|
dst->numeric = 1;
|
606
609
|
|
607
|
-
/* Perform the
|
610
|
+
/* Perform the multiplication. */
|
608
611
|
dst->data_int = value2integer(src0) * value2integer(src1);
|
609
612
|
return dst;
|
610
613
|
}
|
@@ -620,12 +623,29 @@ static Value div_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
|
620
623
|
dst->type = src0->type;
|
621
624
|
dst->numeric = 1;
|
622
625
|
|
623
|
-
/* Perform the
|
626
|
+
/* Perform the division. */
|
624
627
|
dst->data_int = value2integer(src0) / value2integer(src1);
|
625
628
|
return dst;
|
626
629
|
}
|
627
630
|
|
628
631
|
|
632
|
+
/** Computes the modulo of two defined bitstring values.
|
633
|
+
* @param src0 the first source value of the addition
|
634
|
+
* @param src1 the second source value of the addition
|
635
|
+
* @param dst the destination value
|
636
|
+
* @return dst */
|
637
|
+
static Value mod_value_defined_bitstring(Value src0, Value src1, Value dst) {
|
638
|
+
/* Sets state of the destination using the first source. */
|
639
|
+
dst->type = src0->type;
|
640
|
+
dst->numeric = 1;
|
641
|
+
|
642
|
+
/* Perform the modulo. */
|
643
|
+
// printf("modulo with src0=%lld src1=%lld, result=%lld\n",value2integer(src0),value2integer(src1),value2integer(src0) % value2integer(src1));
|
644
|
+
dst->data_int = value2integer(src0) % value2integer(src1);
|
645
|
+
return dst;
|
646
|
+
}
|
647
|
+
|
648
|
+
|
629
649
|
/** Computes the lesser comparision of two defined bitstring values.
|
630
650
|
* @param src0 the first source value of the addition
|
631
651
|
* @param src1 the second source value of the addition
|
@@ -1334,10 +1354,11 @@ Value read_range_bitstring(Value src, long long first, long long last,
|
|
1334
1354
|
* @param src the source value
|
1335
1355
|
* @param first the first index of the range
|
1336
1356
|
* @param last the last index of the range
|
1357
|
+
* @param base the type of the elements
|
1337
1358
|
* @param dst the destination value
|
1338
1359
|
* @return dst */
|
1339
1360
|
Value write_range_bitstring(Value src, long long first, long long last,
|
1340
|
-
Value dst) {
|
1361
|
+
Type base, Value dst) {
|
1341
1362
|
unsigned long long i;
|
1342
1363
|
/* Ensure first is the smaller. */
|
1343
1364
|
if (first > last) {
|
@@ -1350,7 +1371,8 @@ Value write_range_bitstring(Value src, long long first, long long last,
|
|
1350
1371
|
unsigned long long src_width = type_width(src->type);
|
1351
1372
|
unsigned long long dst_width = type_width(dst->type);
|
1352
1373
|
/* scale the range according to the base type. */
|
1353
|
-
unsigned long long bw = dst->type->base;
|
1374
|
+
// unsigned long long bw = dst->type->base;
|
1375
|
+
unsigned long long bw = type_width(base);
|
1354
1376
|
first *= bw;
|
1355
1377
|
last *= bw;
|
1356
1378
|
last += bw-1;
|
@@ -1371,10 +1393,11 @@ Value write_range_bitstring(Value src, long long first, long long last,
|
|
1371
1393
|
* @param src the source value
|
1372
1394
|
* @param first the first index of the range
|
1373
1395
|
* @param last the last index of the range
|
1396
|
+
* @param base the type of the elements
|
1374
1397
|
* @param dst the destination value
|
1375
1398
|
* @return dst */
|
1376
1399
|
Value write_range_bitstring_no_z(Value src, long long first, long long last,
|
1377
|
-
Value dst) {
|
1400
|
+
Type base, Value dst) {
|
1378
1401
|
unsigned long long i;
|
1379
1402
|
/* Ensure first is the smaller. */
|
1380
1403
|
if (first > last) {
|
@@ -1386,7 +1409,8 @@ Value write_range_bitstring_no_z(Value src, long long first, long long last,
|
|
1386
1409
|
unsigned long long src_width = type_width(src->type);
|
1387
1410
|
unsigned long long dst_width = type_width(dst->type);
|
1388
1411
|
/* scale the range according to the base type. */
|
1389
|
-
unsigned long long bw = dst->type->base;
|
1412
|
+
// unsigned long long bw = dst->type->base;
|
1413
|
+
unsigned long long bw = type_width(base);
|
1390
1414
|
first *= bw;
|
1391
1415
|
last *= bw;
|
1392
1416
|
/* Access the source and destination bitstring data. */
|
@@ -1415,7 +1439,10 @@ fix_numeric_type(Type type, unsigned long long val) {
|
|
1415
1439
|
/* Get the width of the type. */
|
1416
1440
|
int width = type_width(type);
|
1417
1441
|
/* Compute the base mask. */
|
1418
|
-
unsigned long long mask = ((unsigned long long)(-1)) << width;
|
1442
|
+
// unsigned long long mask = ((unsigned long long)(-1)) << width;
|
1443
|
+
/* NOTE: (ull)-1 << 64 becomes (ull)-1 on Intel processors, this is
|
1444
|
+
* totally not what I expected (I expected 0). */
|
1445
|
+
unsigned long long mask = width == 64 ? 0 : ((unsigned long long)(-1)) << width;
|
1419
1446
|
// printf("width=%i val=%llu mask=%llx\n",width,val,mask);
|
1420
1447
|
|
1421
1448
|
/* Is the type signed? */
|
@@ -1516,6 +1543,23 @@ static Value div_value_numeric(Value src0, Value src1, Value dst) {
|
|
1516
1543
|
}
|
1517
1544
|
|
1518
1545
|
|
1546
|
+
/** Computes the modulo of two numeric values.
|
1547
|
+
* @param src0 the first source value of the addition
|
1548
|
+
* @param src1 the second source value of the addition
|
1549
|
+
* @param dst the destination value
|
1550
|
+
* @return dst */
|
1551
|
+
static Value mod_value_numeric(Value src0, Value src1, Value dst) {
|
1552
|
+
/* Sets state of the destination using the first source. */
|
1553
|
+
dst->type = src0->type;
|
1554
|
+
dst->numeric = 1;
|
1555
|
+
|
1556
|
+
/* Perform the division. */
|
1557
|
+
// printf("modulo numeric with src0=%lld src1=%lld, result=%lld\n",src0->data_int, src1->data_int,src0->data_int % src1->data_int);
|
1558
|
+
dst->data_int = fix_numeric_type(dst->type, src0->data_int % src1->data_int);
|
1559
|
+
return dst;
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
|
1519
1563
|
/** Computes the NOT of a numeric value.
|
1520
1564
|
* @param src the source value of the not
|
1521
1565
|
* @param dst the destination value
|
@@ -1690,7 +1734,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1690
1734
|
unsigned int i,pos;
|
1691
1735
|
/* Compute the bit width of the destination. */
|
1692
1736
|
unsigned int width = 0;
|
1693
|
-
// printf("concat_value_numeric with dir=%d\n",dir);
|
1737
|
+
// printf("concat_value_numeric with dir=%d and width=%llu\n",dir,type_width(args[0]->type));
|
1694
1738
|
for(i=0; i<num; ++i) width += type_width(args[i]->type);
|
1695
1739
|
|
1696
1740
|
/* Sets state of the destination using the bit width. */
|
@@ -1714,6 +1758,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1714
1758
|
pos += arg_width;
|
1715
1759
|
}
|
1716
1760
|
/* Return the destination. */
|
1761
|
+
// printf("Result is dst=%llx\n",dst->data_int);
|
1717
1762
|
return dst;
|
1718
1763
|
}
|
1719
1764
|
|
@@ -1724,6 +1769,7 @@ static Value concat_value_numeric_array(int num, int dir,
|
|
1724
1769
|
* @param dst the destination value
|
1725
1770
|
* @return dst */
|
1726
1771
|
static Value cast_value_numeric(Value src, Type type, Value dst) {
|
1772
|
+
// printf("cast_value_numeric with src=%llx",src->data_int);
|
1727
1773
|
/* Copy the source to the destination. */
|
1728
1774
|
dst->data_int = src->data_int;
|
1729
1775
|
/* Update the destination type to the cast. */
|
@@ -1783,6 +1829,7 @@ static int same_content_value_range_numeric(Value value0,
|
|
1783
1829
|
* @return dst */
|
1784
1830
|
Value read_range_numeric(Value value, long long first, long long last,
|
1785
1831
|
Type base, Value dst) {
|
1832
|
+
/* printf("read_range_numeric with value=%llx and first=%llu and last=%llu\n",value->data_int,first,last); */
|
1786
1833
|
/* Ensure first is the smaller. */
|
1787
1834
|
if (first > last) {
|
1788
1835
|
long long tmp = last;
|
@@ -1795,15 +1842,18 @@ Value read_range_numeric(Value value, long long first, long long last,
|
|
1795
1842
|
unsigned long long bw = type_width(base);
|
1796
1843
|
/* Scale the range according to the base type. */
|
1797
1844
|
first *= bw;
|
1845
|
+
last *= bw;
|
1798
1846
|
length *= bw;
|
1799
|
-
|
1847
|
+
/* printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length); */
|
1800
1848
|
|
1801
1849
|
/* Set the type and size of the destination from the type of the source.*/
|
1802
1850
|
dst->type = make_type_vector(get_type_bit(),length);
|
1803
1851
|
dst->numeric = 1;
|
1804
1852
|
|
1805
1853
|
/* Compute the read mask. */
|
1806
|
-
unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
|
1854
|
+
// unsigned long long mask = ((-1LL) << first) & (~((-1LL) << (last+1)));
|
1855
|
+
/* NOTE: once again, << 64 does not work like expected. */
|
1856
|
+
unsigned long long mask = mask+bw < 64 ? (~((-1LL) << (last+bw))) : -1LL;
|
1807
1857
|
/* Performs the read. */
|
1808
1858
|
unsigned long long data = (value->data_int & mask) >> first;
|
1809
1859
|
/* Write it to the destination. */
|
@@ -1818,10 +1868,11 @@ Value read_range_numeric(Value value, long long first, long long last,
|
|
1818
1868
|
* @param src the source value
|
1819
1869
|
* @param first the first index of the range
|
1820
1870
|
* @param last the last index of the range
|
1871
|
+
* @param base the type of the elements
|
1821
1872
|
* @param dst the destination value
|
1822
1873
|
* @return dst */
|
1823
1874
|
Value write_range_numeric(Value src, long long first, long long last,
|
1824
|
-
Value dst) {
|
1875
|
+
Type base, Value dst) {
|
1825
1876
|
// printf("write_range_numeric\n");
|
1826
1877
|
/* Ensure first is the smaller. */
|
1827
1878
|
if (first > last) {
|
@@ -1833,7 +1884,8 @@ Value write_range_numeric(Value src, long long first, long long last,
|
|
1833
1884
|
unsigned long long src_width = type_width(src->type);
|
1834
1885
|
unsigned long long dst_width = type_width(dst->type);
|
1835
1886
|
/* scale the range according to the base type of the destination. */
|
1836
|
-
unsigned long long bw = dst->type->base;
|
1887
|
+
// unsigned long long bw = dst->type->base;
|
1888
|
+
unsigned long long bw = type_width(base);
|
1837
1889
|
// printf("src_width=%llu dst_wdith=%llu bw=%llu\n",src_width,dst_width,bw);
|
1838
1890
|
first *= bw;
|
1839
1891
|
last *= bw;
|
@@ -1999,6 +2051,33 @@ Value div_value(Value src0, Value src1, Value dst) {
|
|
1999
2051
|
}
|
2000
2052
|
|
2001
2053
|
|
2054
|
+
/** Computes the modulo of two general values.
|
2055
|
+
* @param src0 the first source value of the addition
|
2056
|
+
* @param src1 the second source value of the addition
|
2057
|
+
* @param dst the destination value
|
2058
|
+
* @return dst */
|
2059
|
+
Value mod_value(Value src0, Value src1, Value dst) {
|
2060
|
+
/* Might allocate a new value so save the current pool state. */
|
2061
|
+
unsigned int pos = get_value_pos();
|
2062
|
+
/* Do a numeric computation if possible, otherwise fallback to bitstring
|
2063
|
+
* computation. */
|
2064
|
+
if (src0->numeric && src1->numeric) {
|
2065
|
+
/* Both sources are numeric. */
|
2066
|
+
return mod_value_numeric(src0,src1,dst);
|
2067
|
+
} else if (is_defined_value(src0) && is_defined_value(src1)) {
|
2068
|
+
/* Both sources can be converted to numeric values. */
|
2069
|
+
return mod_value_defined_bitstring(src0,src1,dst);
|
2070
|
+
} else {
|
2071
|
+
/* Cannot compute (for now), simply undefines the destination. */
|
2072
|
+
/* First ensure dst has the right shape. */
|
2073
|
+
copy_value(src0,dst);
|
2074
|
+
/* Then make it undefined. */
|
2075
|
+
set_undefined_bitstring(dst);
|
2076
|
+
}
|
2077
|
+
return dst;
|
2078
|
+
}
|
2079
|
+
|
2080
|
+
|
2002
2081
|
/** Computes the NOT of a general value.
|
2003
2082
|
* @param src the source value of the not
|
2004
2083
|
* @param dst the destination value
|
@@ -2618,14 +2697,17 @@ Value read_range(Value value, long long first, long long last, Type base,
|
|
2618
2697
|
* @param src the source value
|
2619
2698
|
* @param first the first index of the range
|
2620
2699
|
* @param last the last index of the range
|
2700
|
+
* @param base the type of the elements
|
2621
2701
|
* @param dst the destination value
|
2622
2702
|
* @return dst */
|
2623
|
-
Value write_range(Value src, long long first, long long last,
|
2703
|
+
Value write_range(Value src, long long first, long long last, Type base,
|
2704
|
+
Value dst) {
|
2624
2705
|
// printf("write_range\n");
|
2625
2706
|
/* Is the value numeric? */
|
2626
2707
|
if ((src->numeric) && (dst->numeric)) {
|
2627
2708
|
/* Yes, do a numeric range read. */
|
2628
|
-
return write_range_numeric(src,first,last,dst);
|
2709
|
+
// return write_range_numeric(src,first,last,dst);
|
2710
|
+
return write_range_numeric(src,first,last,base,dst);
|
2629
2711
|
} else {
|
2630
2712
|
/* No, do a bitstring range read. */
|
2631
2713
|
if (dst->numeric) {
|
@@ -2635,7 +2717,8 @@ Value write_range(Value src, long long first, long long last, Value dst) {
|
|
2635
2717
|
/* Need to convert the source to a bitstring. */
|
2636
2718
|
src = set_bitstring_value(src,get_value());
|
2637
2719
|
}
|
2638
|
-
return write_range_bitstring(src,first,last,dst);
|
2720
|
+
// return write_range_bitstring(src,first,last,dst);
|
2721
|
+
return write_range_bitstring(src,first,last,base,dst);
|
2639
2722
|
}
|
2640
2723
|
}
|
2641
2724
|
|
@@ -2644,14 +2727,16 @@ Value write_range(Value src, long long first, long long last, Value dst) {
|
|
2644
2727
|
* @param src the source value
|
2645
2728
|
* @param first the first index of the range
|
2646
2729
|
* @param last the last index of the range
|
2730
|
+
* @param base the type of the elements
|
2647
2731
|
* @param dst the destination value
|
2648
2732
|
* @return dst */
|
2649
|
-
Value write_range_no_z(Value src, long long first, long long last,
|
2733
|
+
Value write_range_no_z(Value src, long long first, long long last, Type base,
|
2734
|
+
Value dst) {
|
2650
2735
|
// printf("write_range_no_z\n");
|
2651
2736
|
/* Is the value numeric? */
|
2652
2737
|
if ((src->numeric) && (dst->numeric)) {
|
2653
2738
|
/* Yes, do a numeric range read. */
|
2654
|
-
return write_range_numeric(src,first,last,dst);
|
2739
|
+
return write_range_numeric(src,first,last,base,dst);
|
2655
2740
|
} else {
|
2656
2741
|
/* No, do a bitstring range read. */
|
2657
2742
|
if (dst->numeric) {
|
@@ -2661,7 +2746,8 @@ Value write_range_no_z(Value src, long long first, long long last, Value dst) {
|
|
2661
2746
|
/* Need to convert the source to a bitstring. */
|
2662
2747
|
src = set_bitstring_value(src,get_value());
|
2663
2748
|
}
|
2664
|
-
return write_range_bitstring_no_z(src,first,last,dst);
|
2749
|
+
// return write_range_bitstring_no_z(src,first,last,dst);
|
2750
|
+
return write_range_bitstring_no_z(src,first,last,base,dst);
|
2665
2751
|
}
|
2666
2752
|
}
|
2667
2753
|
|
@@ -365,6 +365,7 @@ void* behavior_run(void* arg) {
|
|
365
365
|
* @note create a thread per timed behavior. */
|
366
366
|
void hruby_sim_start_timed_behaviors() {
|
367
367
|
int i;
|
368
|
+
pthread_mutex_lock(&hruby_sim_mutex);
|
368
369
|
/* Sets the end flags to 0. */
|
369
370
|
sim_end_flag = 0;
|
370
371
|
/* Create and start the threads. */
|
@@ -375,6 +376,7 @@ void hruby_sim_start_timed_behaviors() {
|
|
375
376
|
pthread_create(&timed_behaviors[i]->thread,NULL,
|
376
377
|
&behavior_run,timed_behaviors[i]);
|
377
378
|
}
|
379
|
+
pthread_mutex_unlock(&hruby_sim_mutex);
|
378
380
|
}
|
379
381
|
|
380
382
|
/** Ends waiting all the threads properly terminates. */
|
@@ -497,12 +499,18 @@ void transmit_to_signal_range(Value value, RefRangeS ref) {
|
|
497
499
|
SignalI signal = ref.signal;
|
498
500
|
unsigned long long first = ref.first;
|
499
501
|
unsigned long long last = ref.last;
|
502
|
+
/* The base type is stored here to avoid allocating a new type each time.
|
503
|
+
* It have an arbitrary base size a single element. */
|
504
|
+
static TypeS baseT = { 1, 1 };
|
505
|
+
baseT.base = signal->f_value->type->base;
|
500
506
|
// printf("Tansmit to signal range: %s(%p) [%lld:%lld]\n",signal->name,signal,first,last);
|
501
507
|
/* Can transmit, copy the content. */
|
502
508
|
if (signal->fading)
|
503
|
-
signal->f_value = write_range(value,first,last,
|
509
|
+
signal->f_value = write_range(value,first,last,&baseT,
|
510
|
+
signal->f_value);
|
504
511
|
else
|
505
|
-
signal->f_value = write_range_no_z(value,first,last,
|
512
|
+
signal->f_value = write_range_no_z(value,first,last,&baseT,
|
513
|
+
signal->f_value);
|
506
514
|
/* And touch the signal. */
|
507
515
|
touch_signal(signal);
|
508
516
|
}
|
@@ -551,9 +559,9 @@ void transmit_to_signal_range_seq(Value value, RefRangeS ref) {
|
|
551
559
|
// printf("Tansmit to signal range: %s(%p)\n",signal->name,signal);
|
552
560
|
/* Can transmit, copy the content. */
|
553
561
|
if (signal->fading)
|
554
|
-
write_range(value,first,last,signal->f_value);
|
562
|
+
write_range(value,first,last,signal->f_value->type,signal->f_value);
|
555
563
|
else
|
556
|
-
write_range_no_z(value,first,last,signal->f_value);
|
564
|
+
write_range_no_z(value,first,last,signal->f_value->type,signal->f_value);
|
557
565
|
/* And touch the signal. */
|
558
566
|
touch_signal_seq(signal);
|
559
567
|
}
|
data/lib/HDLRuby/std/channel.rb
CHANGED
@@ -81,20 +81,31 @@ module HDLRuby::High::Std
|
|
81
81
|
end
|
82
82
|
|
83
83
|
|
84
|
-
##
|
85
|
-
# Module for wrapping channel ports.
|
86
|
-
module ChannelPortWrapping
|
84
|
+
# ##
|
85
|
+
# # Module for wrapping channel ports.
|
86
|
+
# module ChannelPortWrapping
|
87
|
+
# # Wrap with +args+ arguments.
|
88
|
+
# def wrap(*args)
|
89
|
+
# return ChannelPortB.new(self,*args)
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
|
93
|
+
## Describes a channel port.
|
94
|
+
class ChannelPort
|
87
95
|
# Wrap with +args+ arguments.
|
88
96
|
def wrap(*args)
|
89
97
|
return ChannelPortB.new(self,*args)
|
90
98
|
end
|
99
|
+
|
100
|
+
# The scope the port has been declared in.
|
101
|
+
attr_reader :scope
|
91
102
|
end
|
92
103
|
|
93
104
|
|
94
105
|
##
|
95
106
|
# Describes a read port to a channel.
|
96
|
-
class ChannelPortR
|
97
|
-
include ChannelPortWrapping
|
107
|
+
class ChannelPortR < ChannelPort
|
108
|
+
# include ChannelPortWrapping
|
98
109
|
|
99
110
|
# Creates a new channel reader running in +namespace+ and
|
100
111
|
# reading using +reader_proc+ and reseting using +reseter_proc+.
|
@@ -105,6 +116,7 @@ module HDLRuby::High::Std
|
|
105
116
|
@namespace = namespace
|
106
117
|
@reader_proc = reader_proc.to_proc
|
107
118
|
@rester_proc = reseter_proc ? reseter_proc.to_proc : proc {}
|
119
|
+
@scope = HDLRuby::High.cur_scope
|
108
120
|
end
|
109
121
|
|
110
122
|
## Performs a read on the channel using +args+ and +ruby_block+
|
@@ -137,8 +149,8 @@ module HDLRuby::High::Std
|
|
137
149
|
|
138
150
|
##
|
139
151
|
# Describes a writer port to a channel.
|
140
|
-
class ChannelPortW
|
141
|
-
include ChannelPortWrapping
|
152
|
+
class ChannelPortW < ChannelPort
|
153
|
+
# include ChannelPortWrapping
|
142
154
|
|
143
155
|
# Creates a new channel writer running in +namespace+ and
|
144
156
|
# writing using +writer_proc+ and reseting using +reseter_proc+.
|
@@ -149,6 +161,7 @@ module HDLRuby::High::Std
|
|
149
161
|
@namespace = namespace
|
150
162
|
@writer_proc = writer_proc.to_proc
|
151
163
|
@reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
|
164
|
+
@scope = HDLRuby::High.cur_scope
|
152
165
|
end
|
153
166
|
|
154
167
|
## Performs a write on the channel using +args+ and +ruby_block+
|
@@ -181,8 +194,8 @@ module HDLRuby::High::Std
|
|
181
194
|
|
182
195
|
##
|
183
196
|
# Describes an access port to a channel.
|
184
|
-
class ChannelPortA
|
185
|
-
include ChannelPortWrapping
|
197
|
+
class ChannelPortA < ChannelPort
|
198
|
+
# include ChannelPortWrapping
|
186
199
|
|
187
200
|
# Creates a new channel accesser running in +namespace+
|
188
201
|
# and reading using +reader_proc+, writing using +writer_proc+,
|
@@ -198,6 +211,7 @@ module HDLRuby::High::Std
|
|
198
211
|
@reader_proc = reader_proc ? reader_proc.to_proc : proc { }
|
199
212
|
@writer_proc = writer_proc ? writer_proc.to_proc : proc { }
|
200
213
|
@reseter_proc = reseter_proc ? reseter_proc.to_proc : proc {}
|
214
|
+
@scope = HDLRuby::High.cur_scope
|
201
215
|
end
|
202
216
|
|
203
217
|
## Performs a read on the channel using +args+ and +ruby_block+
|
@@ -243,8 +257,8 @@ module HDLRuby::High::Std
|
|
243
257
|
|
244
258
|
##
|
245
259
|
# Describes port wrapper (Box) for fixing arugments.
|
246
|
-
class ChannelPortB
|
247
|
-
include ChannelPortWrapping
|
260
|
+
class ChannelPortB < ChannelPort
|
261
|
+
# include ChannelPortWrapping
|
248
262
|
|
249
263
|
# Creates a new channel box over channel port +port+ fixing +args+
|
250
264
|
# as arguments.
|
@@ -273,6 +287,8 @@ module HDLRuby::High::Std
|
|
273
287
|
@args_write = args.clone
|
274
288
|
@args_access = args.clone
|
275
289
|
end
|
290
|
+
|
291
|
+
@scope = @port.scope
|
276
292
|
end
|
277
293
|
|
278
294
|
## Performs a read on the channel using +args+ and +ruby_block+
|
@@ -324,6 +340,12 @@ module HDLRuby::High::Std
|
|
324
340
|
# building a channel.
|
325
341
|
attr_reader :namespace
|
326
342
|
|
343
|
+
# The read port if any.
|
344
|
+
attr_reader :read_port
|
345
|
+
|
346
|
+
# The write port if any.
|
347
|
+
attr_reader :write_port
|
348
|
+
|
327
349
|
## Creates a new channel instance with +name+ built from +ruby_block+.
|
328
350
|
def initialize(name,&ruby_block)
|
329
351
|
# Check and set the name of the channel.
|
@@ -338,6 +360,10 @@ module HDLRuby::High::Std
|
|
338
360
|
# Keep access to self.
|
339
361
|
obj = self
|
340
362
|
|
363
|
+
# At first there no read nor write port.
|
364
|
+
@read_port = nil
|
365
|
+
@write_port = nil
|
366
|
+
|
341
367
|
# The reader input ports by name.
|
342
368
|
@reader_inputs = {}
|
343
369
|
# The reader output ports by name.
|
@@ -359,11 +385,6 @@ module HDLRuby::High::Std
|
|
359
385
|
# The accesser inout ports by name.
|
360
386
|
@accesser_inouts = {}
|
361
387
|
|
362
|
-
# # The default reset procedures (reseters), by default do nothing.
|
363
|
-
# @input_reseter_proc = proc {}
|
364
|
-
# @output_reseter_proc = proc {}
|
365
|
-
# @inout_reseter_proc = proc {}
|
366
|
-
|
367
388
|
# The branch channels
|
368
389
|
@branches = {}
|
369
390
|
|
@@ -419,6 +440,11 @@ module HDLRuby::High::Std
|
|
419
440
|
HDLRuby::High.space_reg(@name) { obj }
|
420
441
|
end
|
421
442
|
|
443
|
+
# Get the parent system.
|
444
|
+
def parent_system
|
445
|
+
return self.scope.parent_system
|
446
|
+
end
|
447
|
+
|
422
448
|
# The methods for defining the channel
|
423
449
|
|
424
450
|
# For the channel itself
|
@@ -598,15 +624,30 @@ module HDLRuby::High::Std
|
|
598
624
|
@writer_inouts.values
|
599
625
|
end
|
600
626
|
|
627
|
+
## Tells if the channel support inout port.
|
628
|
+
def inout?
|
629
|
+
return @accesser_inputs.any? || @accesser_outputs.any? ||
|
630
|
+
@accesser_inouts.any?
|
631
|
+
end
|
632
|
+
|
601
633
|
# Defines a branch in the channel named +name+ built executing
|
602
634
|
# +ruby_block+.
|
603
|
-
|
635
|
+
# Alternatively, a ready channel instance can be passed as argument
|
636
|
+
# as +channelI+.
|
637
|
+
def brancher(name,channelI = nil,&ruby_block)
|
604
638
|
# Ensure name is a symbol.
|
605
639
|
name = name.to_s unless name.respond_to?(:to_sym)
|
606
640
|
name = name.to_sym
|
607
|
-
#
|
608
|
-
channelI
|
641
|
+
# Is there a ready channel instance.
|
642
|
+
if channelI then
|
643
|
+
# Yes, use it directly.
|
644
|
+
@branches[name] = channelI
|
645
|
+
return self
|
646
|
+
end
|
647
|
+
# Now, create the branch.
|
648
|
+
channelI = HDLRuby::High::Std.channel_instance(name, &ruby_block)
|
609
649
|
@branches[name] = channelI
|
650
|
+
return self
|
610
651
|
end
|
611
652
|
|
612
653
|
|
@@ -619,60 +660,90 @@ module HDLRuby::High::Std
|
|
619
660
|
name = name.to_s unless name.respond_to?(:to_sym)
|
620
661
|
name = name.to_sym
|
621
662
|
# Get the branch.
|
663
|
+
channelI = @branches[name]
|
622
664
|
return @branches[name]
|
623
665
|
end
|
624
666
|
|
625
667
|
|
626
668
|
# Reader, writer and accesser side.
|
627
669
|
|
628
|
-
## Declares the
|
629
|
-
def input(name)
|
670
|
+
## Declares the reader port as and assigned them to +name+.
|
671
|
+
def input(name = nil)
|
630
672
|
# Ensure name is a symbol.
|
673
|
+
name = HDLRuby.uniq_name unless name
|
631
674
|
name = name.to_sym
|
675
|
+
# Ensure the port is not already existing.
|
676
|
+
if @read_port then
|
677
|
+
raise "Read port already declared for channel instance: " +
|
678
|
+
self.name
|
679
|
+
end
|
680
|
+
|
632
681
|
# Access the ports
|
633
|
-
loc_inputs = @reader_inputs
|
634
|
-
loc_outputs = @reader_outputs
|
635
|
-
loc_inouts = @reader_inouts
|
682
|
+
# loc_inputs = @reader_inputs
|
683
|
+
# loc_outputs = @reader_outputs
|
684
|
+
# loc_inouts = @reader_inouts
|
685
|
+
loc_inputs = @reader_inputs.merge(@accesser_inputs)
|
686
|
+
loc_outputs = @reader_outputs.merge(@accesser_outputs)
|
687
|
+
loc_inouts = @reader_inouts.merge(@accesser_inouts)
|
688
|
+
locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
|
636
689
|
# The generated port with corresponding channel port pairs.
|
637
690
|
port_pairs = []
|
638
|
-
|
639
|
-
|
640
|
-
#
|
641
|
-
|
642
|
-
|
643
|
-
|
691
|
+
if HDLRuby::High.cur_system == self.parent_system then
|
692
|
+
# Port in same system as the channel case.
|
693
|
+
# Add them to the current system.
|
694
|
+
HDLRuby::High.cur_system.open do
|
695
|
+
locs.each do |name,sig|
|
696
|
+
port_pairs << [sig, sig.type.inner(name)]
|
697
|
+
end
|
644
698
|
end
|
645
|
-
|
646
|
-
|
647
|
-
|
699
|
+
obj = self
|
700
|
+
# Make the inner connection
|
701
|
+
port_pairs.each do |sig, port|
|
702
|
+
sig.parent.open do
|
703
|
+
port.to_ref <= sig
|
704
|
+
end
|
648
705
|
end
|
649
|
-
|
650
|
-
|
651
|
-
|
706
|
+
else
|
707
|
+
# Port in different system as the channel case.
|
708
|
+
# Add them to the current system.
|
709
|
+
HDLRuby::High.cur_system.open do
|
710
|
+
# The inputs
|
711
|
+
loc_inputs.each do |name,sig|
|
712
|
+
# puts "name=#{name} sig.name=#{sig.name}"
|
713
|
+
port_pairs << [sig, sig.type.input(name)]
|
714
|
+
end
|
715
|
+
# The outputs
|
716
|
+
loc_outputs.each do |name,sig|
|
717
|
+
port_pairs << [sig, sig.type.output(name)]
|
718
|
+
end
|
719
|
+
# The inouts
|
720
|
+
loc_inouts.each do |name,sig|
|
721
|
+
port_pairs << [sig, sig.type.inout(name)]
|
722
|
+
end
|
652
723
|
end
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
724
|
+
obj = self
|
725
|
+
# Make the connection of the instance.
|
726
|
+
HDLRuby::High.cur_system.on_instance do |inst|
|
727
|
+
obj.scope.open do
|
728
|
+
port_pairs.each do |sig, port|
|
729
|
+
RefObject.new(inst,port.to_ref) <= sig
|
730
|
+
end
|
660
731
|
end
|
661
732
|
end
|
662
733
|
end
|
663
734
|
|
664
735
|
# Fill the reader namespace with the access to the reader signals.
|
665
|
-
|
736
|
+
loc_inputs.each do |name,sig|
|
666
737
|
@reader_namespace.add_method(sig.name) do
|
667
738
|
HDLRuby::High.top_user.send(name)
|
668
739
|
end
|
669
740
|
end
|
670
|
-
|
741
|
+
loc_outputs.each do |name,sig|
|
671
742
|
@reader_namespace.add_method(sig.name) do
|
672
743
|
HDLRuby::High.top_user.send(name)
|
673
744
|
end
|
674
745
|
end
|
675
|
-
|
746
|
+
loc_inouts.each do |name,sig|
|
676
747
|
@reader_namespace.add_method(sig.name) do
|
677
748
|
HDLRuby::High.top_user.send(name)
|
678
749
|
end
|
@@ -682,56 +753,88 @@ module HDLRuby::High::Std
|
|
682
753
|
# NOTE: for now, simply associate the channel to name.
|
683
754
|
chp = ChannelPortR.new(@reader_namespace,@reader_proc,@input_reseter_proc)
|
684
755
|
HDLRuby::High.space_reg(name) { chp }
|
756
|
+
# Save the port in the channe to avoid conflicting declaration.
|
757
|
+
@read_port = chp
|
685
758
|
return chp
|
686
759
|
end
|
687
760
|
|
688
761
|
## Declares the ports for the writer and assigned them to +name+.
|
689
|
-
def output(name)
|
762
|
+
def output(name = nil)
|
690
763
|
# Ensure name is a symbol.
|
764
|
+
name = HDLRuby.uniq_name unless name
|
691
765
|
name = name.to_sym
|
766
|
+
# Ensure the port is not already existing.
|
767
|
+
if @write_port then
|
768
|
+
raise "Write port already declared for channel instance: " +
|
769
|
+
self.name
|
770
|
+
end
|
692
771
|
# Access the ports
|
693
|
-
loc_inputs = @writer_inputs
|
694
|
-
loc_outputs = @writer_outputs
|
695
|
-
loc_inouts = @writer_inouts
|
772
|
+
# loc_inputs = @writer_inputs
|
773
|
+
# loc_outputs = @writer_outputs
|
774
|
+
# loc_inouts = @writer_inouts
|
775
|
+
loc_inputs = @writer_inputs.merge(@accesser_inputs)
|
776
|
+
loc_outputs = @writer_outputs.merge(@accesser_outputs)
|
777
|
+
loc_inouts = @writer_inouts.merge(@accesser_inouts)
|
778
|
+
locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
|
696
779
|
# The generated port with corresponding channel port pairs.
|
697
780
|
port_pairs = []
|
698
|
-
#
|
699
|
-
HDLRuby::High.cur_system.
|
700
|
-
#
|
701
|
-
|
702
|
-
|
781
|
+
# puts "cur_system=#{HDLRuby::High.cur_system} self.parent_system=#{self.parent_system}"
|
782
|
+
if HDLRuby::High.cur_system == self.parent_system then
|
783
|
+
# puts "Inner found!"
|
784
|
+
# Port in same system as the channel case.
|
785
|
+
# Add them to the current system.
|
786
|
+
HDLRuby::High.cur_system.open do
|
787
|
+
locs.each do |name,sig|
|
788
|
+
port_pairs << [sig, sig.type.inner(name)]
|
789
|
+
end
|
703
790
|
end
|
704
|
-
|
705
|
-
|
706
|
-
|
791
|
+
obj = self
|
792
|
+
# Make the inner connection
|
793
|
+
port_pairs.each do |sig, port|
|
794
|
+
sig.parent.open do
|
795
|
+
port.to_ref <= sig
|
796
|
+
end
|
707
797
|
end
|
708
|
-
|
709
|
-
|
710
|
-
|
798
|
+
else
|
799
|
+
# Portds in different system as the channel's case.
|
800
|
+
# Add them to the current system.
|
801
|
+
HDLRuby::High.cur_system.open do
|
802
|
+
# The inputs
|
803
|
+
loc_inputs.each do |name,sig|
|
804
|
+
port_pairs << [sig, sig.type.input(name)]
|
805
|
+
end
|
806
|
+
# The outputs
|
807
|
+
loc_outputs.each do |name,sig|
|
808
|
+
port_pairs << [sig, sig.type.output(name)]
|
809
|
+
end
|
810
|
+
# The inouts
|
811
|
+
loc_inouts.each do |name,sig|
|
812
|
+
port_pairs << [sig, sig.type.inout(name)]
|
813
|
+
end
|
711
814
|
end
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
815
|
+
obj = self
|
816
|
+
# Make the connection of the instance.
|
817
|
+
HDLRuby::High.cur_system.on_instance do |inst|
|
818
|
+
obj.scope.open do
|
819
|
+
port_pairs.each do |sig, port|
|
820
|
+
RefObject.new(inst,port.to_ref) <= sig
|
821
|
+
end
|
719
822
|
end
|
720
823
|
end
|
721
824
|
end
|
722
825
|
|
723
826
|
# Fill the writer namespace with the access to the writer signals.
|
724
|
-
|
827
|
+
loc_inputs.each do |name,sig|
|
725
828
|
@writer_namespace.add_method(sig.name) do
|
726
829
|
HDLRuby::High.top_user.send(name)
|
727
830
|
end
|
728
831
|
end
|
729
|
-
|
832
|
+
loc_outputs.each do |name,sig|
|
730
833
|
@writer_namespace.add_method(sig.name) do
|
731
834
|
HDLRuby::High.top_user.send(name)
|
732
835
|
end
|
733
836
|
end
|
734
|
-
|
837
|
+
loc_inouts.each do |name,sig|
|
735
838
|
@writer_namespace.add_method(sig.name) do
|
736
839
|
HDLRuby::High.top_user.send(name)
|
737
840
|
end
|
@@ -741,73 +844,28 @@ module HDLRuby::High::Std
|
|
741
844
|
# NOTE: for now, simply associate the channel to name.
|
742
845
|
chp = ChannelPortW.new(@writer_namespace,@writer_proc,@output_reseter_proc)
|
743
846
|
HDLRuby::High.space_reg(name) { chp }
|
847
|
+
# Save the port in the channe to avoid conflicting declaration.
|
848
|
+
@write_port = chp
|
744
849
|
return chp
|
745
850
|
end
|
746
851
|
|
747
|
-
|
748
|
-
|
852
|
+
|
853
|
+
## Declares the accesser port and assigned them to +name+.
|
854
|
+
def inout(name = nil)
|
749
855
|
# Ensure name is a symbol.
|
856
|
+
name = HDLRuby.uniq_name unless name
|
750
857
|
name = name.to_sym
|
751
|
-
#
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
# The generated port with corresponding channel port pairs.
|
756
|
-
port_pairs = []
|
757
|
-
# Add them to the current system.
|
758
|
-
HDLRuby::High.cur_system.open do
|
759
|
-
# The inputs
|
760
|
-
loc_inputs.each do |name,sig|
|
761
|
-
port_pairs << [sig, sig.type.input(name)]
|
762
|
-
end
|
763
|
-
# The outputs
|
764
|
-
loc_outputs.each do |name,sig|
|
765
|
-
port_pairs << [sig, sig.type.output(name)]
|
766
|
-
end
|
767
|
-
# The inouts
|
768
|
-
loc_inouts.each do |name,sig|
|
769
|
-
port_pairs << [sig, sig.type.inout(name)]
|
770
|
-
end
|
771
|
-
end
|
772
|
-
obj = self
|
773
|
-
# Make the connection of the instance.
|
774
|
-
HDLRuby::High.cur_system.on_instance do |inst|
|
775
|
-
obj.scope.open do
|
776
|
-
port_pairs.each do |sig, port|
|
777
|
-
RefObject.new(inst,port.to_ref) <= sig
|
778
|
-
end
|
779
|
-
end
|
858
|
+
# Ensure the port is not already existing.
|
859
|
+
if @read_port then
|
860
|
+
raise "Read port already declared for channel instance: " +
|
861
|
+
self.name
|
780
862
|
end
|
781
863
|
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
HDLRuby::High.top_user.send(name)
|
786
|
-
end
|
787
|
-
end
|
788
|
-
@accesser_outputs.each do |name,sig|
|
789
|
-
@accesser_namespace.add_method(sig.name) do
|
790
|
-
HDLRuby::High.top_user.send(name)
|
791
|
-
end
|
792
|
-
end
|
793
|
-
@accesser_inouts.each do |name,sig|
|
794
|
-
@accesser_namespace.add_method(sig.name) do
|
795
|
-
HDLRuby::High.top_user.send(name)
|
796
|
-
end
|
864
|
+
if @write_port then
|
865
|
+
raise "Write port already declared for channel instance: " +
|
866
|
+
self.name
|
797
867
|
end
|
798
868
|
|
799
|
-
# Give access to the ports through name.
|
800
|
-
# NOTE: for now, simply associate the channel to name.
|
801
|
-
chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
|
802
|
-
HDLRuby::High.space_reg(name) { chp }
|
803
|
-
return chp
|
804
|
-
end
|
805
|
-
|
806
|
-
## Declares the ports for accessing the channel as an inner component
|
807
|
-
# and assigned them to +name+.
|
808
|
-
def inner(name)
|
809
|
-
# Ensure name is a symbol.
|
810
|
-
name = name.to_sym
|
811
869
|
# Access the ports
|
812
870
|
loc_inputs = @accesser_inputs.merge(@reader_inputs).
|
813
871
|
merge(@writer_inputs)
|
@@ -818,21 +876,51 @@ module HDLRuby::High::Std
|
|
818
876
|
locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
|
819
877
|
# The generated port with corresponding channel port pairs.
|
820
878
|
port_pairs = []
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
879
|
+
if HDLRuby::High.cur_system == self.parent_system then
|
880
|
+
# Port in same system as the channel case.
|
881
|
+
# Add them to the current system.
|
882
|
+
HDLRuby::High.cur_system.open do
|
883
|
+
locs.each do |name,sig|
|
884
|
+
port_pairs << [sig, sig.type.inner(name)]
|
885
|
+
end
|
825
886
|
end
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
887
|
+
obj = self
|
888
|
+
# Make the inner connection
|
889
|
+
port_pairs.each do |sig, port|
|
890
|
+
sig.parent.open do
|
891
|
+
port.to_ref <= sig
|
892
|
+
end
|
893
|
+
end
|
894
|
+
else
|
895
|
+
# Port in different system as the channel case.
|
896
|
+
# Add them to the current system.
|
897
|
+
HDLRuby::High.cur_system.open do
|
898
|
+
# The inputs
|
899
|
+
loc_inputs.each do |name,sig|
|
900
|
+
# puts "name=#{name} sig.name=#{sig.name}"
|
901
|
+
port_pairs << [sig, sig.type.input(name)]
|
902
|
+
end
|
903
|
+
# The outputs
|
904
|
+
loc_outputs.each do |name,sig|
|
905
|
+
port_pairs << [sig, sig.type.output(name)]
|
906
|
+
end
|
907
|
+
# The inouts
|
908
|
+
loc_inouts.each do |name,sig|
|
909
|
+
port_pairs << [sig, sig.type.inout(name)]
|
910
|
+
end
|
911
|
+
end
|
912
|
+
obj = self
|
913
|
+
# Make the connection of the instance.
|
914
|
+
HDLRuby::High.cur_system.on_instance do |inst|
|
915
|
+
obj.scope.open do
|
916
|
+
port_pairs.each do |sig, port|
|
917
|
+
RefObject.new(inst,port.to_ref) <= sig
|
918
|
+
end
|
919
|
+
end
|
832
920
|
end
|
833
921
|
end
|
834
922
|
|
835
|
-
#
|
923
|
+
# Fill the reader namespace with the access to the reader signals.
|
836
924
|
loc_inputs.each do |name,sig|
|
837
925
|
@accesser_namespace.add_method(sig.name) do
|
838
926
|
HDLRuby::High.top_user.send(name)
|
@@ -853,37 +941,121 @@ module HDLRuby::High::Std
|
|
853
941
|
# NOTE: for now, simply associate the channel to name.
|
854
942
|
chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
|
855
943
|
HDLRuby::High.space_reg(name) { chp }
|
944
|
+
# Save the port in the channe to avoid conflicting declaration.
|
945
|
+
@read_port = chp
|
946
|
+
@write_port = chp
|
856
947
|
return chp
|
857
948
|
end
|
858
949
|
|
950
|
+
# ## Declares the ports for accessing the channel as an inner component
|
951
|
+
# # and assigned them to +name+.
|
952
|
+
# def inner(name)
|
953
|
+
# # Ensure name is a symbol.
|
954
|
+
# name = name.to_sym
|
955
|
+
# # Access the ports
|
956
|
+
# loc_inputs = @accesser_inputs.merge(@reader_inputs).
|
957
|
+
# merge(@writer_inputs)
|
958
|
+
# loc_outputs = @accesser_outputs.merge(@reader_outputs).
|
959
|
+
# merge(@writer_outputs)
|
960
|
+
# loc_inouts = @accesser_inouts.merge(@reader_inouts).
|
961
|
+
# merge(@writer_inouts)
|
962
|
+
# locs = loc_inputs.merge(loc_outputs).merge(loc_inouts)
|
963
|
+
# # The generated port with corresponding channel port pairs.
|
964
|
+
# port_pairs = []
|
965
|
+
# # Add them to the current system.
|
966
|
+
# HDLRuby::High.cur_system.open do
|
967
|
+
# locs.each do |name,sig|
|
968
|
+
# port_pairs << [sig, sig.type.inner(name)]
|
969
|
+
# end
|
970
|
+
# end
|
971
|
+
# obj = self
|
972
|
+
# # Make the inner connection
|
973
|
+
# port_pairs.each do |sig, port|
|
974
|
+
# sig.parent.open do
|
975
|
+
# port.to_ref <= sig
|
976
|
+
# end
|
977
|
+
# end
|
978
|
+
|
979
|
+
# # Set ups the accesser's namespace
|
980
|
+
# loc_inputs.each do |name,sig|
|
981
|
+
# @accesser_namespace.add_method(sig.name) do
|
982
|
+
# HDLRuby::High.top_user.send(name)
|
983
|
+
# end
|
984
|
+
# end
|
985
|
+
# loc_outputs.each do |name,sig|
|
986
|
+
# @accesser_namespace.add_method(sig.name) do
|
987
|
+
# HDLRuby::High.top_user.send(name)
|
988
|
+
# end
|
989
|
+
# end
|
990
|
+
# loc_inouts.each do |name,sig|
|
991
|
+
# @accesser_namespace.add_method(sig.name) do
|
992
|
+
# HDLRuby::High.top_user.send(name)
|
993
|
+
# end
|
994
|
+
# end
|
995
|
+
|
996
|
+
# # Give access to the ports through name.
|
997
|
+
# # NOTE: for now, simply associate the channel to name.
|
998
|
+
# chp = ChannelPortA.new(@accesser_namespace,@reader_proc,@writer_proc,@inout_reseter_proc)
|
999
|
+
# HDLRuby::High.space_reg(name) { chp }
|
1000
|
+
# return chp
|
1001
|
+
# end
|
1002
|
+
|
1003
|
+
|
859
1004
|
|
860
1005
|
## Performs a read on the channel using +args+ and +ruby_block+
|
861
1006
|
# as arguments.
|
1007
|
+
# NOTE:
|
1008
|
+
# * Will generate a port if not present.
|
1009
|
+
# * Will generate an error if a read is tempted while the read
|
1010
|
+
# port has been declared within another system.
|
862
1011
|
def read(*args,&ruby_block)
|
863
|
-
#
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
1012
|
+
# Is there a port to read?
|
1013
|
+
unless self.read_port then
|
1014
|
+
# No, generate a new one.
|
1015
|
+
# Is it possible to be inout?
|
1016
|
+
if self.inout? then
|
1017
|
+
# Yes, create an inout port.
|
1018
|
+
self.inout(HDLRuby.uniq_name)
|
1019
|
+
else
|
1020
|
+
# No, create an input port.
|
1021
|
+
self.input(HDLRuby.uniq_name)
|
1022
|
+
end
|
870
1023
|
end
|
871
|
-
|
1024
|
+
# Ensure the read port is within current system.
|
1025
|
+
unless self.read_port.scope.system != HDLRuby::High.cur_system then
|
1026
|
+
raise "Cannot read from a port external of current system for channel " + self.name
|
1027
|
+
end
|
1028
|
+
# Performs the read.
|
1029
|
+
self.read_port.read(*args,&ruby_block)
|
872
1030
|
end
|
873
1031
|
|
874
1032
|
## Performs a write on the channel using +args+ and +ruby_block+
|
875
1033
|
# as arguments.
|
1034
|
+
# NOTE:
|
1035
|
+
# * Will generate a port if not present.
|
1036
|
+
# * Will generate an error if a read is tempted while the read
|
1037
|
+
# port has been declared within another system.
|
876
1038
|
def write(*args,&ruby_block)
|
877
|
-
#
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
1039
|
+
# Is there a port to write?
|
1040
|
+
unless self.write_port then
|
1041
|
+
# No, generate a new one.
|
1042
|
+
# Is it possible to be inout?
|
1043
|
+
if self.inout? then
|
1044
|
+
# Yes, create an inout port.
|
1045
|
+
self.inout(HDLRuby.uniq_name)
|
1046
|
+
else
|
1047
|
+
# No, create an output port.
|
1048
|
+
self.output(HDLRuby.uniq_name)
|
1049
|
+
end
|
884
1050
|
end
|
885
|
-
|
1051
|
+
# Ensure the write port is within current system.
|
1052
|
+
unless self.write_port.scope.system != HDLRuby::High.cur_system then
|
1053
|
+
raise "Cannot write from a port external of current system for channel " + self.name
|
1054
|
+
end
|
1055
|
+
# Performs the write.
|
1056
|
+
self.write_port.write(*args,&ruby_block)
|
886
1057
|
end
|
1058
|
+
|
887
1059
|
|
888
1060
|
## Performs a reset on the channel using +args+ and +ruby_block+
|
889
1061
|
# as arguments.
|
@@ -902,10 +1074,12 @@ module HDLRuby::High::Std
|
|
902
1074
|
|
903
1075
|
|
904
1076
|
# Wrapper to make an object run like a channel port.
|
905
|
-
class ChannelPortObject
|
1077
|
+
class ChannelPortObject < ChannelPort
|
906
1078
|
# Create a new object wrapper for +obj+.
|
907
1079
|
def initialize(obj)
|
908
1080
|
@obj = obj
|
1081
|
+
|
1082
|
+
@scope = HDLRuby::High.cur_scope
|
909
1083
|
end
|
910
1084
|
|
911
1085
|
# Port read with arguments +args+ executing +ruby_block+ in
|
@@ -946,9 +1120,13 @@ module HDLRuby::High::Std
|
|
946
1120
|
|
947
1121
|
|
948
1122
|
# Wrap object +obj+ to act like a channel port.
|
949
|
-
def channel_port(obj)
|
1123
|
+
def self.channel_port(obj)
|
1124
|
+
return obj if obj.is_a?(ChannelPort) # No need to wrap.
|
950
1125
|
return ChannelPortObject.new(obj)
|
951
1126
|
end
|
1127
|
+
def channel_port(obj)
|
1128
|
+
return HDLRuby::High::Std.channel_port(obj)
|
1129
|
+
end
|
952
1130
|
end
|
953
1131
|
|
954
1132
|
|