1
+ from amaranth .hdl ._ast import *
2
+
3
+
4
+ def _eval_matches (test , patterns ):
5
+ if patterns is None :
6
+ return True
7
+ for pattern in patterns :
8
+ if isinstance (pattern , str ):
9
+ mask = int ("" .join ("0" if b == "-" else "1" for b in pattern ), 2 )
10
+ value = int ("" .join ("0" if b == "-" else b for b in pattern ), 2 )
11
+ if value == (mask & test ):
12
+ return True
13
+ else :
14
+ if pattern == test :
15
+ return True
16
+ return False
17
+
18
+
19
+ def eval_value (sim , value ):
20
+ if isinstance (value , Const ):
21
+ return value .value
22
+ elif isinstance (value , Operator ):
23
+ if len (value .operands ) == 1 :
24
+ op_a = eval_value (sim , value .operands [0 ])
25
+ if value .operator in ("u" , "s" ):
26
+ width = value .shape ().width
27
+ res = op_a
28
+ res &= (1 << width ) - 1
29
+ if value .operator == "s" and res & (1 << (width - 1 )):
30
+ res |= - 1 << (width - 1 )
31
+ return res
32
+ elif value .operator == "-" :
33
+ return - op_a
34
+ elif value .operator == "~" :
35
+ shape = value .shape ()
36
+ if shape .signed :
37
+ return ~ op_a
38
+ else :
39
+ return ~ op_a & ((1 << shape .width ) - 1 )
40
+ elif value .operator in ("b" , "r|" ):
41
+ return int (op_a != 0 )
42
+ elif value .operator == "r&" :
43
+ width = value .operands [0 ].shape ().width
44
+ mask = (1 << width ) - 1
45
+ return int ((op_a & mask ) == mask )
46
+ elif value .operator == "r^" :
47
+ width = value .operands [0 ].shape ().width
48
+ mask = (1 << width ) - 1
49
+ # Believe it or not, this is the fastest way to compute a sideways XOR in Python.
50
+ return format (op_a & mask , 'b' ).count ('1' ) % 2
51
+ elif len (value .operands ) == 2 :
52
+ op_a = eval_value (sim , value .operands [0 ])
53
+ op_b = eval_value (sim , value .operands [1 ])
54
+ if value .operator == "|" :
55
+ return op_a | op_b
56
+ elif value .operator == "&" :
57
+ return op_a & op_b
58
+ elif value .operator == "^" :
59
+ return op_a ^ op_b
60
+ elif value .operator == "+" :
61
+ return op_a + op_b
62
+ elif value .operator == "-" :
63
+ return op_a - op_b
64
+ elif value .operator == "*" :
65
+ return op_a * op_b
66
+ elif value .operator == "//" :
67
+ if op_b == 0 :
68
+ return 0
69
+ return op_a // op_b
70
+ elif value .operator == "%" :
71
+ if op_b == 0 :
72
+ return 0
73
+ return op_a % op_b
74
+ elif value .operator == "<<" :
75
+ return op_a << op_b
76
+ elif value .operator == ">>" :
77
+ return op_a >> op_b
78
+ elif value .operator == "==" :
79
+ return int (op_a == op_b )
80
+ elif value .operator == "!=" :
81
+ return int (op_a != op_b )
82
+ elif value .operator == "<" :
83
+ return int (op_a < op_b )
84
+ elif value .operator == "<=" :
85
+ return int (op_a <= op_b )
86
+ elif value .operator == ">" :
87
+ return int (op_a > op_b )
88
+ elif value .operator == ">=" :
89
+ return int (op_a >= op_b )
90
+ assert False # :nocov:
91
+ elif isinstance (value , Slice ):
92
+ res = eval_value (sim , value .value )
93
+ res >>= value .start
94
+ width = value .stop - value .start
95
+ return res & ((1 << width ) - 1 )
96
+ elif isinstance (value , Part ):
97
+ res = eval_value (sim , value .value )
98
+ offset = eval_value (sim , value .offset )
99
+ offset *= value .stride
100
+ res >>= offset
101
+ return res & ((1 << value .width ) - 1 )
102
+ elif isinstance (value , Concat ):
103
+ res = 0
104
+ pos = 0
105
+ for part in value .parts :
106
+ width = len (part )
107
+ part = eval_value (sim , part )
108
+ part &= (1 << width ) - 1
109
+ res |= part << pos
110
+ pos += width
111
+ return res
112
+ elif isinstance (value , SwitchValue ):
113
+ test = eval_value (sim , value .test )
114
+ for patterns , val in value .cases :
115
+ if _eval_matches (test , patterns ):
116
+ return eval_value (sim , val )
117
+ return 0
118
+ elif isinstance (value , Signal ):
119
+ slot = sim .get_signal (value )
120
+ return sim .slots [slot ].curr
121
+ elif isinstance (value , (ResetSignal , ClockSignal , AnyValue , Initial )):
122
+ raise ValueError (f"Value { value !r} cannot be used in simulation" )
123
+ else :
124
+ assert False # :nocov:
125
+
126
+
127
+ def _eval_assign_inner (sim , lhs , lhs_start , rhs , rhs_len ):
128
+ if isinstance (lhs , Operator ) and lhs .operator in ("u" , "s" ):
129
+ _eval_assign_inner (sim , lhs .operands [0 ], lhs_start , rhs , rhs_len )
130
+ elif isinstance (lhs , Signal ):
131
+ lhs_stop = lhs_start + rhs_len
132
+ if lhs_stop > len (lhs ):
133
+ lhs_stop = len (lhs )
134
+ if lhs_start >= len (lhs ):
135
+ return
136
+ slot = sim .get_signal (lhs )
137
+ value = sim .slots [slot ].next
138
+ mask = (1 << lhs_stop ) - (1 << lhs_start )
139
+ value &= ~ mask
140
+ value |= (rhs << lhs_start ) & mask
141
+ value &= (1 << len (lhs )) - 1
142
+ if lhs ._signed and (value & (1 << (len (lhs ) - 1 ))):
143
+ value |= - 1 << (len (lhs ) - 1 )
144
+ sim .slots [slot ].set (value )
145
+ elif isinstance (lhs , Slice ):
146
+ _eval_assign_inner (sim , lhs .value , lhs_start + lhs .start , rhs , rhs_len )
147
+ elif isinstance (lhs , Concat ):
148
+ part_stop = 0
149
+ for part in lhs .parts :
150
+ part_start = part_stop
151
+ part_len = len (part )
152
+ part_stop = part_start + part_len
153
+ if lhs_start >= part_stop :
154
+ continue
155
+ if lhs_start + rhs_len <= part_start :
156
+ continue
157
+ if lhs_start < part_start :
158
+ part_lhs_start = 0
159
+ part_rhs_start = part_start - lhs_start
160
+ else :
161
+ part_lhs_start = lhs_start - part_start
162
+ part_rhs_start = 0
163
+ if lhs_start + rhs_len >= part_stop :
164
+ part_rhs_len = part_stop - lhs_start - part_rhs_start
165
+ else :
166
+ part_rhs_len = rhs_len - part_rhs_start
167
+ part_rhs = rhs >> part_rhs_start
168
+ part_rhs &= (1 << part_rhs_len ) - 1
169
+ _eval_assign_inner (sim , part , part_lhs_start , part_rhs , part_rhs_len )
170
+ elif isinstance (lhs , Part ):
171
+ offset = eval_value (sim , lhs .offset )
172
+ offset *= lhs .stride
173
+ _eval_assign_inner (sim , lhs .value , lhs_start + offset , rhs , rhs_len )
174
+ elif isinstance (lhs , SwitchValue ):
175
+ test = eval_value (sim , lhs .test )
176
+ for patterns , val in lhs .cases :
177
+ if _eval_matches (test , patterns ):
178
+ _eval_assign_inner (sim , val , lhs_start , rhs , rhs_len )
179
+ return
180
+ else :
181
+ raise ValueError (f"Value { lhs !r} cannot be assigned" )
182
+
183
+ def eval_assign (sim , lhs , value ):
184
+ _eval_assign_inner (sim , lhs , 0 , value , len (lhs ))
0 commit comments