1"""
2========================================================================
3NamedObject_test.py
4========================================================================
5
6Author : Shunning Jiang
7Date   : Dec 23, 2017
8"""
9from pymtl3.dsl.errors import FieldReassignError
10from pymtl3.dsl.NamedObject import NamedObject
11
12
13class Chicken(NamedObject):
14
15  def construct( s ):
16    s.protein = NamedObject()
17
18class Dog(NamedObject):
19
20  def construct( s ):
21    s.chicken = Chicken()
22
23class Tiger(NamedObject):
24
25  def construct( s ):
26    s.rooster = Chicken()
27
28class Human(NamedObject):
29
30  def construct( s, nlunch=1, ndinner=1 ):
31
32    if nlunch == 1: s.lunch = Tiger()
33    else:           s.lunch = [ Tiger() for _ in range(nlunch) ]
34
35    if ndinner == 1: s.dinner = Dog()
36    else:            s.dinner = [ Dog() for _ in range(ndinner) ]
37
38def test_NamedObject_normal():
39
40  x = Human( nlunch=1, ndinner=1 )
41  x.elaborate()
42
43  assert repr(x) == "s"
44
45  assert repr(x.lunch) == "s.lunch"
46  assert repr(x.dinner) == "s.dinner"
47
48  assert repr(x.lunch.rooster) == "s.lunch.rooster"
49  assert repr(x.dinner.chicken)== "s.dinner.chicken"
50
51  assert repr(x.lunch.rooster.protein) == "s.lunch.rooster.protein"
52  assert repr(x.dinner.chicken.protein)== "s.dinner.chicken.protein"
53  print(x.dinner.chicken.protein)
54
55def test_NamedObject_list1():
56
57  x = Human( nlunch=1, ndinner=5 )
58  x.elaborate()
59
60  assert repr(x) == "s"
61
62  assert repr(x.lunch) == "s.lunch"
63  assert repr(x.dinner[2]) == "s.dinner[2]"
64
65  assert repr(x.lunch.rooster) == "s.lunch.rooster"
66  assert repr(x.dinner[2].chicken)== "s.dinner[2].chicken"
67
68  assert repr(x.lunch.rooster.protein) == "s.lunch.rooster.protein"
69  assert repr(x.dinner[1].chicken.protein)== "s.dinner[1].chicken.protein"
70  print(x.dinner[1].chicken.protein)
71
72def test_NamedObject_list2():
73
74  x = Human( nlunch=4, ndinner=1 )
75  x.elaborate()
76
77  assert repr(x) == "s"
78
79  assert repr(x.lunch[3]) == "s.lunch[3]"
80  assert repr(x.dinner) == "s.dinner"
81
82  assert repr(x.lunch[3].rooster) == "s.lunch[3].rooster"
83  assert repr(x.dinner.chicken) == "s.dinner.chicken"
84
85  assert repr(x.lunch[3].rooster.protein) == "s.lunch[3].rooster.protein"
86  assert repr(x.dinner.chicken.protein) == "s.dinner.chicken.protein"
87  print(repr(x.lunch[3].rooster.protein))
88
89# FIXME
90def test_use_init_error():
91
92  class Crocodile(NamedObject):
93
94    def __init__( s ):
95      s.food = Dog()
96      print(s.food.chicken)
97
98  # x = Chicken()
99  # x.elaborate()
100  # y = Crocodile()
101  # y.elaborate()
102  # z = Chicken()
103  # z.elaborate()
104
105def test_invalid_reassignment_attr():
106
107  class Donkey( NamedObject ):
108    def construct( s ):
109      s.x = Dog()
110      s.x = Dog()
111
112  x = Donkey()
113  try:
114    x.elaborate()
115  except FieldReassignError as e:
116    print(e)
117    assert str(e).startswith("The attempt to assign hardware construct to field")
118    return
119  raise Exception("Should've thrown FieldReassignError")
120
121def test_invalid_reassignment_list():
122
123  class Donkey( NamedObject ):
124    def construct( s ):
125      s.x = Dog()
126      s.x = [ Dog() for _ in range(4) ]
127
128  x = Donkey()
129  try:
130    x.elaborate()
131  except FieldReassignError as e:
132    print(e)
133    assert str(e).startswith("The attempt to assign hardware construct to field")
134    return
135  raise Exception("Should've thrown FieldReassignError")
136
137def test_set_param():
138
139  class HoneyBadger( NamedObject ):
140    def construct( s, lunch="dirt", dinner="dirt" ):
141      s.lunch  = lunch
142      s.dinner = dinner
143
144  class Dromaius( NamedObject ):
145    def construct( s, lunch="dirt", dinner="dirt" ):
146      s.lunch  = lunch
147      s.dinner = dinner
148
149  class Panda( NamedObject ):
150    def construct( s, lunch="dirt", dinner="dirt" ):
151      s.lunch  = lunch
152      s.dinner = dinner
153
154  class Zoo( NamedObject ):
155    def construct( s, AnimalTypes=[] ):
156      s.animals = [ A() for A in AnimalTypes ]
157
158  A = Dromaius()
159  A.set_param( "top.construct", lunch="grass" )
160  A.elaborate()
161
162  print( A.lunch )
163  assert A.lunch  == "grass"
164  assert A.dinner == "dirt"
165
166  Z = Zoo()
167  Z.set_param( "top.construct", AnimalTypes=[ HoneyBadger, Dromaius, Panda ] )
168  Z.set_param( "top.animals[0].construct", dinner="bamboo" )
169  Z.set_param( "top.animals*.construct",
170      lunch ="grass",
171      dinner="poisoned onion",
172  )
173  Z.set_param( "top.animals[2].construct", dinner="bamboo" )
174  print( "="*30, "Z", "="*30 )
175  print( Z._dsl.param_tree.leaf )
176  print( Z._dsl.param_tree.children )
177  print( "="*30, "Z.animals[0]", "="*30 )
178  print( Z._dsl.param_tree.children["animals[0]"].leaf )
179  print( Z._dsl.param_tree.children["animals[0]"].children )
180  print( "="*30, "Z.animals*", "="*30 )
181  print( Z._dsl.param_tree.children["animals*"].leaf )
182  print( Z._dsl.param_tree.children["animals*"].children )
183  print( "="*30, "Z.animals[2]", "="*30 )
184  print( Z._dsl.param_tree.children["animals[2]"].leaf )
185  print( Z._dsl.param_tree.children["animals[2]"].children )
186  Z.elaborate()
187  print( "="*30, "animals[0]", "="*30 )
188  print( Z.animals[0]._dsl.param_tree.leaf )
189  print( Z.animals[1]._dsl.param_tree.children )
190  print( "="*30, "animals[1]", "="*30 )
191  print( Z.animals[0]._dsl.param_tree.leaf )
192  print( Z.animals[1]._dsl.param_tree.children )
193  print( "="*30, "animals[2]", "="*30 )
194  print( Z.animals[0]._dsl.param_tree.leaf )
195  print( Z.animals[1]._dsl.param_tree.children )
196
197  assert Z.animals[0].lunch  == "grass"
198  assert Z.animals[1].lunch  == "grass"
199  assert Z.animals[2].lunch  == "grass"
200  assert Z.animals[0].dinner == "poisoned onion"
201  assert Z.animals[1].dinner == "poisoned onion"
202  assert Z.animals[2].dinner == "bamboo"
203