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/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
|
|