Skip to content

Commit 7159e2c

Browse files
committed
thread is updated for fixed point operation support.
1 parent 4b0ee23 commit 7159e2c

File tree

3 files changed

+114
-53
lines changed

3 files changed

+114
-53
lines changed

veriloggen/thread/compiler.py

Lines changed: 95 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
import textwrap
99

1010
import veriloggen.core.vtypes as vtypes
11-
11+
import veriloggen.types.fixed as fixed
1212
from . import optimizer
1313
from .scope import ScopeName, ScopeFrameList, ScopeFrame
14-
from .operator import getVeriloggenOp
14+
from .operator import getVeriloggenOp, getMethodName
15+
from . import fixed_intrinsics as fi
16+
1517

18+
numerical_types = vtypes.numerical_types
1619

1720
_tmp_count = 0
1821

@@ -45,18 +48,6 @@ def visit_FunctionDef(self, node):
4548
self.functions[node.name] = node
4649

4750

48-
class TargetVisitor(ast.NodeVisitor):
49-
50-
def visit_List(self, node):
51-
return [self.visit(elt) for elt in node.elts]
52-
53-
def visit_Tuple(self, node):
54-
return [self.visit(elt) for elt in node.elts]
55-
56-
def visit_Name(self, node):
57-
return node.id
58-
59-
6051
class CompileVisitor(ast.NodeVisitor):
6152

6253
def __init__(self, m, name, clk, rst, fsm,
@@ -76,7 +67,19 @@ def __init__(self, m, name, clk, rst, fsm,
7667
self.local_objects = local_objects
7768
self.datawidth = datawidth
7869

79-
self.targetvisitor = TargetVisitor()
70+
# fixed intrinsics
71+
fixed_intrinsics = {
72+
'FixedInput': fi._intrinsic_FixedInput,
73+
'FixedOutput': fi._intrinsic_FixedOutput,
74+
'FixedOutputReg': fi._intrinsic_FixedOutputReg,
75+
'FixedReg': fi._intrinsic_FixedReg,
76+
'FixedWire': fi._intrinsic_FixedWire,
77+
'to_fixed': fi._intrinsic_to_fixed,
78+
'fixed_to_int': fi._intrinsic_fixed_to_int,
79+
'fixed_to_int_low': fi._intrinsic_fixed_to_int_low,
80+
'fixed_to_real': fi._intrinsic_fixed_to_real,
81+
}
82+
self.intrinsic_functions.update(fixed_intrinsics)
8083

8184
self.scope = ScopeFrameList()
8285
self.loop_info = OrderedDict()
@@ -104,28 +107,39 @@ def visit_Assign(self, node):
104107

105108
right = self.visit(node.value)
106109
lefts = [self.visit(target) for target in node.targets]
107-
raw_lefts = [self.targetvisitor.visit(target)
108-
for target in node.targets]
109110

110-
for raw_left, left in zip(raw_lefts, lefts):
111-
self._assign(raw_left, left, right)
111+
for left in lefts:
112+
self._assign(left, right)
112113

113114
self.setFsm()
114115
self.incFsmCount()
115116

116-
def _assign(self, raw_left, left, right):
117-
raw_dsts = raw_left if isinstance(
118-
raw_left, (tuple, list)) else (raw_left,)
117+
def _variable_type(self, right):
118+
if isinstance(right, vtypes._Numeric):
119+
return None
120+
if isinstance(right, fixed._FixedBase):
121+
ret = {'type': 'fixed',
122+
'width': right.bit_length(),
123+
'point': right.point,
124+
'signed': right.signed}
125+
return ret
126+
raise TypeError('unsupported type')
127+
128+
def _assign(self, left, right):
119129
dsts = left if isinstance(left, (tuple, list)) else (left,)
120130

121131
if not isinstance(right, (tuple, list)):
122132
if len(dsts) > 1:
123133
raise ValueError(
124-
"too many values to unpack (expected %d)" % len(right))
125-
self.setAssignBind(raw_dsts[0], dsts[0], right)
134+
"too many values to unpack (expected %d)" % 1)
135+
_type = self._variable_type(right)
136+
var = self.getVariable(dsts[0], store=True, _type=_type)
137+
self.setAssignBind(var, right)
126138

127139
elif len(dsts) == 1:
128-
self.setAssignBind(raw_dsts[0], dsts[0], right)
140+
_type = self._variable_type(right)
141+
var = self.getVariable(dsts[0], store=True, _type=_type)
142+
self.setAssignBind(var, right)
129143

130144
elif len(dsts) < len(right):
131145
raise ValueError(
@@ -136,14 +150,15 @@ def _assign(self, raw_left, left, right):
136150
(len(dsts), len(right)))
137151

138152
else:
139-
for raw_l, l, r in zip(raw_dsts, dsts, right):
140-
self._assign(raw_l, l, r)
153+
for d, r in zip(dsts, right):
154+
self._assign(d, r)
141155

142156
def visit_AugAssign(self, node):
143157
if self.skip():
144158
return
145159
right = self.visit(node.value)
146-
left = self.visit(node.target)
160+
left_name = self.visit(node.target)
161+
left = self.getVariable(left_name, store=True)
147162
op = getVeriloggenOp(node.op)
148163
if op is None:
149164
raise TypeError("Unsupported BinOp: %s" % str(node.op))
@@ -263,7 +278,8 @@ def _for_range(self, node):
263278
if len(node.iter.args) < 3
264279
else self.visit(node.iter.args[2]))
265280

266-
iter_node = self.visit(node.target)
281+
iter_name = self.visit(node.target)
282+
iter_node = self.getVariable(iter_name, store=True)
267283
cond_node = vtypes.LessThan(iter_node, end_node)
268284
update_node = vtypes.Plus(iter_node, step_node)
269285

@@ -326,7 +342,8 @@ def _for_range_fsm(self, begin_node, end_node, step_node,
326342
self.setFsmLoop(check_count, body_end_count, iter_node, step_node)
327343

328344
def _for_list(self, node):
329-
target = self.visit(node.target)
345+
target_name = self.visit(node.target)
346+
target = self.getVariable(target_name, store=True)
330347
iterobj = self.visit(node.iter)
331348

332349
begin_node = vtypes.Int(0)
@@ -341,7 +358,7 @@ def _for_list(self, node):
341358

342359
patterns = []
343360
for i, obj in enumerate(iterobj):
344-
if not isinstance(obj, vtypes.numerical_types):
361+
if not isinstance(obj, numerical_types):
345362
raise TypeError("unsupported type for for-statement")
346363
patterns.append((iter_node == i, obj))
347364
patterns.append((None, vtypes.IntX()))
@@ -454,7 +471,7 @@ def _call_Name_len(self, node):
454471
raise TypeError(
455472
'takes %d positional arguments but %d were given' % (1, len(node.args)))
456473
value = self.visit(node.args[0])
457-
if not isinstance(value, vtypes.numerical_types):
474+
if not isinstance(value, numerical_types):
458475
return len(value)
459476

460477
length = getattr(value, 'length', None)
@@ -782,7 +799,10 @@ def visit_Name(self, node):
782799
return vtypes.Int(0)
783800

784801
store = isinstance(node.ctx, ast.Store)
785-
name = self.getVariable(node.id, store)
802+
if store:
803+
return node.id
804+
805+
name = self.getVariable(node.id)
786806
return name
787807

788808
def visit_Print(self, node):
@@ -837,7 +857,7 @@ def visit_Print(self, node):
837857
def visit_Attribute(self, node):
838858
value = self.visit(node.value)
839859
attr = node.attr
840-
if isinstance(value, vtypes._Variable) and attr == 'value':
860+
if isinstance(value, numerical_types) and attr == 'value':
841861
return value
842862
obj = getattr(value, attr)
843863
return obj
@@ -897,13 +917,34 @@ def skip(self):
897917
val = self.hasBreak() or self.hasContinue() or self.hasReturn()
898918
return val
899919

900-
def makeVariable(self, name, width=None, initval=0):
920+
def makeVariable(self, name, _type=None):
921+
if _type is None:
922+
return self.makeVariableReg(name)
923+
924+
if _type['type'] == 'fixed':
925+
width = _type['width']
926+
point = _type['point']
927+
signed = _type['signed']
928+
return self.makeVariableFixed(name, width, point, signed)
929+
930+
raise TypeError("not supported variable type")
931+
932+
def makeVariableReg(self, name, width=None, initval=0):
901933
signame = _tmp_name('_'.join(['', self.name, name]))
902934
if width is None:
903935
width = self.datawidth
904936
return self.m.Reg(signame, width, initval=initval, signed=True)
905937

906-
def getVariable(self, name, store=False):
938+
def makeVariableFixed(self, name, width=None, point=0, signed=True):
939+
signame = _tmp_name('_'.join(['', self.name, name]))
940+
if width is None:
941+
width = self.datawidth
942+
return fixed.FixedReg(self.m, signame, width=width, point=point, signed=signed)
943+
944+
def getVariable(self, name, store=False, _type=None):
945+
if isinstance(name, vtypes._Numeric):
946+
return name
947+
907948
var = self.scope.searchVariable(name, store)
908949
if var is None:
909950
if not store:
@@ -913,14 +954,14 @@ def getVariable(self, name, store=False):
913954
if glb is not None:
914955
return glb
915956
raise NameError("name '%s' is not defined" % name)
916-
var = self.makeVariable(name)
957+
var = self.makeVariable(name, _type=_type)
917958
self.scope.addVariable(name, var)
918959
var = self.scope.searchVariable(name)
919960
return var
920961

921-
def getTmpVariable(self):
962+
def getTmpVariable(self, _type=None):
922963
name = _tmp_name('tmp')
923-
var = self.getVariable(name, store=True)
964+
var = self.getVariable(name, store=True, _type=_type)
924965
return var
925966

926967
def getGlobalObject(self, name):
@@ -952,42 +993,47 @@ def getFunction(self, name):
952993
raise NameError("function '%s' is not defined" % name)
953994

954995
def setArgBind(self, name, value):
955-
if not isinstance(value, vtypes.numerical_types):
996+
if not isinstance(value, numerical_types):
956997
self.scope.addVariable(name, value)
957998
return
958999

959-
left = self.getVariable(name, store=True)
9601000
right = optimize(value)
1001+
left = self.getVariable(name, store=True)
1002+
9611003
self.setBind(left, right)
9621004

9631005
def setVarargBind(self, name, values):
9641006
lefts = []
9651007
for value in values:
966-
if isinstance(value, vtypes.numerical_types):
967-
left = self.getTmpVariable()
1008+
if isinstance(value, numerical_types):
9681009
right = optimize(value)
1010+
left = self.getTmpVariable()
1011+
9691012
self.setBind(left, right)
9701013
lefts.append(left)
9711014
else:
9721015
lefts.append(value)
9731016
self.scope.addVariable(name, lefts)
9741017

975-
def setAssignBind(self, dst, var, value):
976-
if not isinstance(value, vtypes.numerical_types):
977-
#self.scope.addVariable(dst, value)
978-
# return
1018+
def setAssignBind(self, dst, value):
1019+
if not isinstance(value, numerical_types):
9791020
raise TypeError("dynamic object substitution is not supported")
9801021

981-
self.setBind(var, value)
1022+
self.setBind(dst, value)
9821023

9831024
def setBind(self, var, value, cond=None):
9841025
if var is None:
9851026
cond = None
9861027

1028+
if isinstance(var, fixed._FixedVariable) and isinstance(value, fixed._FixedBase):
1029+
if var.point != value.point:
1030+
raise ValueError("Fixed point not match: %d <- %d" %
1031+
var.point, value.point)
1032+
9871033
value = optimize(value)
9881034
cond = optimize(cond) if cond is not None else None
9891035
subst = (vtypes.SingleStatement(value) if var is None else
990-
vtypes.Subst(var, value))
1036+
var.write(value))
9911037

9921038
if var is not None:
9931039
if hasattr(var, '_fsm') and id(var._fsm) != id(self.fsm):

veriloggen/thread/operator.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import veriloggen.core.vtypes as vtypes
88

9-
109
operators = {
1110
ast.Add: vtypes.Plus,
1211
ast.Sub: vtypes.Minus,
@@ -42,3 +41,16 @@
4241
def getVeriloggenOp(op):
4342
t = type(op)
4443
return operators[t]
44+
45+
46+
methods = {
47+
ast.Add: '__add__',
48+
ast.Sub: '__sub__',
49+
ast.Mult: '__mul__',
50+
ast.Div: '__div__'
51+
}
52+
53+
54+
def getMethodName(op):
55+
t = type(op)
56+
return methods[t]

veriloggen/thread/thread.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ def _synthesize_run_fsm(self, parent_fsm, args, kwargs, cond=None):
304304
if argname not in self.args_dict:
305305
name = compiler._tmp_name(
306306
'_'.join(['', self.name, argname]))
307-
v = self.m.Reg(name, self.datawidth, initval=0, signed=True)
307+
v = self.m.Reg(name, self.datawidth,
308+
initval=0, signed=True)
308309
cvisitor.scope.addVariable(argname, v)
309310
self.args_dict[argname] = v
310311
else:
@@ -378,7 +379,8 @@ def _synthesize_run_fsm(self, parent_fsm, args, kwargs, cond=None):
378379
if argname not in self.args_dict:
379380
name = compiler._tmp_name(
380381
'_'.join(['', self.name, argname]))
381-
v = self.m.Reg(name, self.datawidth, initval=0, signed=True)
382+
v = self.m.Reg(name, self.datawidth,
383+
initval=0, signed=True)
382384
cvisitor.scope.addVariable(argname, v)
383385
self.args_dict[argname] = v
384386
else:
@@ -414,7 +416,8 @@ def _synthesize_run_fsm(self, parent_fsm, args, kwargs, cond=None):
414416
if argname not in self.args_dict:
415417
name = compiler._tmp_name(
416418
'_'.join(['', self.name, argname]))
417-
v = self.m.Reg(name, self.datawidth, initval=0, signed=True)
419+
v = self.m.Reg(name, self.datawidth,
420+
initval=0, signed=True)
418421
cvisitor.scope.addVariable(argname, v)
419422
self.args_dict[argname] = v
420423
else:

0 commit comments

Comments
 (0)