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.
@@ -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, Value dst);
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, Value dst);
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 addition. */
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 addition. */
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
- // printf("first=%lld last=%lld bw=%llu length=%lld\n",first,last,bw,length);
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, Value dst) {
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, Value dst) {
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,signal->f_value);
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,signal->f_value);
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
  }
@@ -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
- def brancher(name,&ruby_block)
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
- # Create the branch.
608
- channelI = HDLRuby::High.channel_instance(name, &ruby_block)
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 ports for the reader and assigned them to +name+.
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
- # Add them to the current system.
639
- HDLRuby::High.cur_system.open do
640
- # The inputs
641
- loc_inputs.each do |name,sig|
642
- # puts "name=#{name} sig.name=#{sig.name}"
643
- port_pairs << [sig, sig.type.input(name)]
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
- # The outputs
646
- loc_outputs.each do |name,sig|
647
- port_pairs << [sig, sig.type.output(name)]
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
- # The inouts
650
- loc_inouts.each do |name,sig|
651
- port_pairs << [sig, sig.type.inout(name)]
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
- end
654
- obj = self
655
- # Make the connection of the instance.
656
- HDLRuby::High.cur_system.on_instance do |inst|
657
- obj.scope.open do
658
- port_pairs.each do |sig, port|
659
- RefObject.new(inst,port.to_ref) <= sig
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
- @reader_inputs.each do |name,sig|
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
- @reader_outputs.each do |name,sig|
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
- @reader_inouts.each do |name,sig|
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
- # Add them to the current system.
699
- HDLRuby::High.cur_system.open do
700
- # The inputs
701
- loc_inputs.each do |name,sig|
702
- port_pairs << [sig, sig.type.input(name)]
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
- # The outputs
705
- loc_outputs.each do |name,sig|
706
- port_pairs << [sig, sig.type.output(name)]
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
- # The inouts
709
- loc_inouts.each do |name,sig|
710
- port_pairs << [sig, sig.type.inout(name)]
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
- end
713
- obj = self
714
- # Make the connection of the instance.
715
- HDLRuby::High.cur_system.on_instance do |inst|
716
- obj.scope.open do
717
- port_pairs.each do |sig, port|
718
- RefObject.new(inst,port.to_ref) <= sig
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
- @writer_inputs.each do |name,sig|
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
- @writer_outputs.each do |name,sig|
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
- @writer_inouts.each do |name,sig|
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
- ## Declares the ports for the accesser and assigned them to +name+.
748
- def inout(name)
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
- # Access the ports
752
- loc_inputs = @accesser_inputs
753
- loc_outputs = @accesser_outputs
754
- loc_inouts = @accesser_inouts
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
- # Set ups the accesser's namespace
783
- @accesser_inputs.each do |name,sig|
784
- @accesser_namespace.add_method(sig.name) do
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
- # Add them to the current system.
822
- HDLRuby::High.cur_system.open do
823
- locs.each do |name,sig|
824
- port_pairs << [sig, sig.type.inner(name)]
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
- end
827
- obj = self
828
- # Make the inner connection
829
- port_pairs.each do |sig, port|
830
- sig.parent.open do
831
- port.to_ref <= sig
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
- # Set ups the accesser's namespace
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
- # Gain access to the reader as local variable.
864
- reader_proc = @reader_proc
865
- # # The context is the one of the reader.
866
- # Execute the code generating the reader in context.
867
- HDLRuby::High.space_push(@namespace)
868
- HDLRuby::High.cur_block.open do
869
- instance_exec(ruby_block,*args,&reader_proc)
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
- HDLRuby::High.space_pop
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
- # Gain access to the writer as local variable.
878
- writer_proc = @writer_proc
879
- # # The context is the one of the writer.
880
- # Execute the code generating the writer in context.
881
- HDLRuby::High.space_push(@namespace)
882
- HDLRuby::High.cur_block.open do
883
- instance_exec(ruby_block,*args,&writer_proc)
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
- HDLRuby::High.space_pop
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