1
1
import operator
2
2
3
3
from migen .fhdl .structure import *
4
- from migen .fhdl .structure import _Operator , _Slice , _Assign , _Fragment
4
+ from migen .fhdl .structure import (_Operator , _Slice , _ArrayProxy ,
5
+ _Assign , _Fragment )
5
6
from migen .fhdl .bitcontainer import flen
6
7
from migen .fhdl .tools import list_targets
7
8
@@ -72,16 +73,21 @@ def commit(self):
72
73
self .modifications .clear ()
73
74
return r
74
75
75
- def eval (self , node ):
76
+ def eval (self , node , postcommit = False ):
76
77
if isinstance (node , Constant ):
77
78
return node .value
78
79
elif isinstance (node , Signal ):
80
+ if postcommit :
81
+ try :
82
+ return self .modifications [node ]
83
+ except KeyError :
84
+ pass
79
85
try :
80
86
return self .signal_values [node ]
81
87
except KeyError :
82
88
return node .reset .value
83
89
elif isinstance (node , _Operator ):
84
- operands = [self .eval (o ) for o in node .operands ]
90
+ operands = [self .eval (o , postcommit ) for o in node .operands ]
85
91
if node .op == "-" :
86
92
if len (operands ) == 1 :
87
93
return - operands [0 ]
@@ -92,7 +98,7 @@ def eval(self, node):
92
98
else :
93
99
return str2op [node .op ](* operands )
94
100
elif isinstance (node , _Slice ):
95
- v = self .eval (node .value )
101
+ v = self .eval (node .value , postcommit )
96
102
idx = range (node .start , node .stop )
97
103
return sum (((v >> i ) & 1 ) << j for j , i in enumerate (idx ))
98
104
elif isinstance (node , Cat ):
@@ -101,29 +107,46 @@ def eval(self, node):
101
107
for element in node .l :
102
108
nbits = flen (element )
103
109
# make value always positive
104
- r |= (self .eval (element ) & (2 ** nbits - 1 )) << shift
110
+ r |= (self .eval (element , postcommit ) & (2 ** nbits - 1 )) << shift
105
111
shift += nbits
106
112
return r
113
+ elif isinstance (node , _ArrayProxy ):
114
+ return self .eval (node .choices [self .eval (node .key , postcommit )],
115
+ postcommit )
107
116
else :
108
- # TODO: Array, ClockSignal, ResetSignal, Memory
117
+ # TODO: ClockSignal, ResetSignal, Memory
109
118
raise NotImplementedError
110
119
111
- def assign (self , signal , value ):
112
- assert not signal .variable
113
- value = value & (2 ** signal .nbits - 1 )
114
- if signal .signed and (value & 2 ** (signal .nbits - 1 )):
115
- value -= 2 ** signal .nbits
116
- self .modifications [signal ] = value
120
+ def assign (self , node , value ):
121
+ if isinstance (node , Signal ):
122
+ assert not node .variable
123
+ value = value & (2 ** node .nbits - 1 )
124
+ if node .signed and (value & 2 ** (node .nbits - 1 )):
125
+ value -= 2 ** node .nbits
126
+ self .modifications [node ] = value
127
+ elif isinstance (node , Cat ):
128
+ for element in node .l :
129
+ nbits = flen (element )
130
+ self .assign (element , value & (2 ** nbits - 1 ))
131
+ value >>= nbits
132
+ elif isinstance (node , Slice ):
133
+ full_value = self .eval (node , True )
134
+ # clear bits assigned to by the slice
135
+ full_value &= ~ ((2 ** node .stop - 1 ) - (2 ** node .start - 1 ))
136
+ # set them to the new value
137
+ value &= 2 ** (node .stop - node .start )- 1
138
+ full_value |= value << node .start
139
+ self .assign (node , full_value )
140
+ elif isinstance (node , _ArrayProxy ):
141
+ self .assign (node .choices [self .eval (node .key )], value )
142
+ else :
143
+ # TODO: ClockSignal, ResetSignal, Memory
144
+ raise NotImplementedError
117
145
118
146
def execute (self , statements ):
119
147
for s in statements :
120
148
if isinstance (s , _Assign ):
121
- value = self .eval (s .r )
122
- if isinstance (s .l , Signal ):
123
- self .assign (s .l , value )
124
- else :
125
- # TODO: Cat, Slice, Array, ClockSignal, ResetSignal, Memory
126
- raise NotImplementedError
149
+ self .assign (s .l , self .eval (s .r ))
127
150
elif isinstance (s , If ):
128
151
if self .eval (s .cond ):
129
152
self .execute (s .t )
@@ -158,7 +181,8 @@ def __init__(self, fragment_or_module, generators, clocks={"sys": 100}):
158
181
else :
159
182
self .generators [k ] = [v ]
160
183
161
- # TODO: insert_resets
184
+ # TODO: insert_resets on sync
185
+ # comb signals return to their reset value if nothing assigns them
162
186
self .fragment .comb [0 :0 ] = [s .eq (s .reset )
163
187
for s in list_targets (self .fragment .comb )]
164
188
0 commit comments