1"""
2========================================================================
3set_param_test.py
4========================================================================
5
6Author : Yanhui Ou, Cheng Tan
7Date   : May 28, 2019
8"""
9from pymtl3.datatypes.bits_import import Bits4, Bits8
10from pymtl3.dsl.Component import Component
11from pymtl3.dsl.ComponentLevel1 import update
12from pymtl3.dsl.ComponentLevel3 import connect
13from pymtl3.dsl.Connectable import InPort, OutPort
14from pymtl3.dsl.NamedObject import NamedObject
15
16from .sim_utils import simple_sim_pass
17
18
19class Animal( NamedObject ):
20  def construct( s, lunch="dirt", dinner="dirt" ):
21    s.lunch  = lunch
22    s.dinner = dinner
23
24class AnimalHouse( NamedObject ):
25  def construct( s, AnimalTypes=[] ):
26    s.animals = [ A() for A in AnimalTypes ]
27
28class HoneyBadger( Animal ):
29  pass
30
31class Dromaius( Animal ):
32  pass
33
34class Panda( Animal ):
35  pass
36
37class Tiger( Animal ):
38  def construct( s, MeatTypes=[], lunch="dirt", dinner="dirt" ):
39    s.meats  = [ Meat() for Meat in MeatTypes ]
40    s.lunch  = lunch
41    s.dinner = dinner
42
43class BabyTiger( Tiger ):
44  pass
45
46class Aquarium( AnimalHouse ):
47  pass
48
49class TigerTerrace( AnimalHouse ):
50  pass
51
52class PandaHouse( AnimalHouse ):
53  pass
54
55class Zoo( NamedObject ):
56  def construct( s, AnimalHouseTypes=[] ):
57    s.houses = [ H() for H in AnimalHouseTypes ]
58
59def test_simple():
60  A = Dromaius()
61  A.set_param( "top.construct", lunch="grass" )
62  A.elaborate()
63
64  print( A.lunch )
65  assert A.lunch  == "grass"
66  assert A.dinner == "dirt"
67
68def test_set_param_overwrite():
69  Z = Zoo()
70  Z.set_param( "top.construct", AnimalHouseTypes=[ PandaHouse, TigerTerrace, AnimalHouse, Aquarium ] )
71  Z.set_param( "top.houses[0].construct", AnimalTypes=[ Panda, Panda, Panda   ] )
72  Z.set_param( "top.houses[1].construct", AnimalTypes=[ Tiger, BabyTiger      ] )
73  Z.set_param( "top.houses[2].construct", AnimalTypes=[ Dromaius, HoneyBadger ] )
74  Z.set_param( "top.houses[1].animals[0].construct", MeatTypes=[ Dromaius, HoneyBadger ] )
75  Z.set_param( "top.houses[0].animals*.construct", lunch="bamboo", dinner="bamboo" )
76  Z.set_param( "top.houses[1].animals[0].meats*.construct", lunch="bamboo" )
77  Z.set_param( "top.houses[1].animals[0].meats[1].construct", lunch="grass" )
78  # The following set_param test tricky overwrite behavior.
79  Z.set_param( "top.houses[2].animals[0].construct", lunch="bugs", dinner="bugs" )
80  Z.set_param( "top.houses[2].animals*.construct", lunch="grass" )
81  Z.set_param( "top.houses[2].animals[0].construct", lunch="bugs" )
82  Z.elaborate()
83
84  assert isinstance( Z.houses[0], PandaHouse )
85  assert isinstance( Z.houses[1], TigerTerrace )
86  assert isinstance( Z.houses[2], AnimalHouse )
87  assert isinstance( Z.houses[3], Aquarium )
88  for i in range( 3 ):
89    assert isinstance( Z.houses[0].animals[i], Panda )
90    assert Z.houses[0].animals[i].lunch  == "bamboo"
91    assert Z.houses[0].animals[i].dinner == "bamboo"
92
93  assert isinstance( Z.houses[1].animals[0], Tiger )
94  assert isinstance( Z.houses[1].animals[1], BabyTiger )
95  assert Z.houses[1].animals[0].meats[0].lunch == "bamboo"
96  assert Z.houses[1].animals[0].meats[1].lunch == "grass"
97
98  assert isinstance( Z.houses[2].animals[0], Dromaius )
99  assert isinstance( Z.houses[2].animals[1], HoneyBadger )
100  # FIXME
101  assert Z.houses[2].animals[0].lunch  == "bugs"
102  assert Z.houses[2].animals[0].dinner == "bugs"
103  assert Z.houses[2].animals[1].lunch  == "grass"
104  assert Z.houses[2].animals[1].dinner == "dirt"
105
106def test_multi_regex():
107  Z = Zoo()
108  Z.set_param( "top.construct", AnimalHouseTypes=[ PandaHouse, TigerTerrace, AnimalHouse, Aquarium ] )
109  Z.set_param( "top.houses[0].construct", AnimalTypes=[ Panda, Panda, Panda   ] )
110  Z.set_param( "top.houses[1].construct", AnimalTypes=[ Tiger, BabyTiger      ] )
111  Z.set_param( "top.houses[2].construct", AnimalTypes=[ Dromaius, HoneyBadger ] )
112  Z.set_param( "top.houses[0].animals[0].construct", lunch="potato", dinner="bamboo" )
113  Z.set_param( "top.houses*.animals*.construct", lunch="onion" )
114  Z.set_param( "top.houses*.animals[0].construct", lunch="potato" )
115  Z.elaborate()
116
117  assert Z.houses[0].animals[0].lunch  == "onion"
118  assert Z.houses[0].animals[0].dinner == "bamboo"
119
120def test_set_param_hierarchical():
121  Z = Zoo()
122
123  Z.set_param( "top.construct", AnimalHouseTypes=[ Aquarium, TigerTerrace ] )
124  Z.set_param( "top.houses[1].construct", AnimalTypes=[ Tiger, Panda ] )
125  Z.set_param( "top.houses*.animals*.construct", lunch="grass" )
126  Z.set_param( "top.houses*.animals[1].construct", lunch="meat" )
127
128  #TODO: Whether we should check throw an error in following scenario
129  Z.set_param( "top.houses*.xxx*.construct", lunch="grass" )
130
131  Z.elaborate()
132
133  assert isinstance(Z.houses[1], TigerTerrace)
134  assert Z.houses[1].animals[0].lunch == "grass"
135  assert Z.houses[1].animals[1].lunch == "meat"
136
137def test_component():
138  class Incr( Component ):
139    def construct( s, DataType=Bits4, incr_value=1 ):
140      s.in_ = InPort ( DataType )
141      s.out = OutPort( DataType )
142
143      s.incr_value = incr_value
144
145      @update
146      def up_incr():
147        s.out @= s.in_ + s.incr_value
148
149  class IncrArray( Component ):
150    def construct( s, num_incrs=1, DataType=Bits4() ):
151      s.in_ = [ InPort ( DataType ) for _ in range( num_incrs ) ]
152      s.out = [ OutPort( DataType ) for _ in range( num_incrs ) ]
153
154      s.incrs = [ Incr( DataType=DataType ) for _ in range( num_incrs ) ]
155
156      for i in range( num_incrs ):
157        connect( s.in_[i], s.incrs[i].in_ )
158        connect( s.out[i], s.incrs[i].out )
159
160  A = Incr()
161  A.set_param( "top.construct", DataType=Bits8, incr_value=2 )
162  A.elaborate()
163  A.apply( simple_sim_pass )
164  A.in_ = 1
165  A.tick()
166  print( "A.out==", A.out )
167  assert A.out == 3
168
169  B = IncrArray()
170  B.set_param( "top.construct", DataType=Bits8, num_incrs=3 )
171  B.set_param( "top.incrs*.construct", incr_value=3 )
172  B.set_param( "top.incrs[2].construct", incr_value=5 )
173  B.elaborate()
174  B.apply( simple_sim_pass )
175  B.in_[0] = 1
176  B.in_[1] = 2
177  B.in_[2] = 3
178  B.tick()
179  assert B.out[0] == 4
180  assert B.out[1] == 5
181  assert B.out[2] == 8
182