def visit_Compare(self, node): left = self.visit(node.left) methods = [getMethodName(op) for op in node.ops] ops = [getVeriloggenOp(op) for op in node.ops] comparators = [self.visit(comp) for comp in node.comparators] rslts = [] for i, (method, op) in enumerate(zip(methods, ops)): if i == 0: try: rslts.append(applyMethod(left, method, comparators[i])) except NotImplementedError: rslts.append(op(left, comparators[i])) else: try: rslts.append( applyMethod(comparators[i - 1], method, comparators[i])) except NotImplementedError: rslts.append(op(comparators[i - 1], comparators[i])) if len(rslts) == 1: return rslts[0] ret = None for r in rslts: if ret: ret = vtypes.Land(ret, r) else: ret = r return ret
def visit_Compare(self, node): left = self.visit(node.left) methods = [getMethodName(op) for op in node.ops] ops = [getVeriloggenOp(op) for op in node.ops] comparators = [self.visit(comp) for comp in node.comparators] rslts = [] for i, (method, op) in enumerate(zip(methods, ops)): if i == 0: if (not isinstance(left, fxd._FixedBase) and isinstance(comparators[i], fxd._FixedBase)): raise TypeError( "type mismatch of operator arguments: '%s' and '%s'" % (str(type(left)), str(type(comparators[i])))) try: rslts.append(applyMethod(left, method, comparators[i])) except NotImplementedError: rslts.append(op(left, comparators[i])) else: if (not isinstance(comparators[i - 1], fxd._FixedBase) and isinstance(comparators[i], fxd._FixedBase)): raise TypeError( "type mismatch of operator arguments: '%s' and '%s'" % (str(type( comparators[i - 1])), str(type(comparators[i])))) try: rslts.append( applyMethod(comparators[i - 1], method, comparators[i])) except NotImplementedError: rslts.append(op(comparators[i - 1], comparators[i])) if len(rslts) == 1: return rslts[0] ret = None for r in rslts: if ret: ret = vtypes.Land(ret, r) else: ret = r return ret
def visit_Compare(self, node): left = self.visit(node.left) ops = [getVeriloggenOp(op) for op in node.ops] comparators = [self.visit(comp) for comp in node.comparators] rslts = [] for i, op in enumerate(ops): if i == 0: rslts.append(op(left, comparators[i])) else: rslts.append(op(comparators[i - 1], comparators[i])) if len(rslts) == 1: return rslts[0] ret = None for r in rslts: if ret: ret = vtypes.Land(ret, r) else: ret = r return ret
def reset(self, fsm, tid): """ reset the FSM counter to the initial state """ for thread in self.threads: if thread.end_state is None: raise ValueError('thread %d not started' % thread.tid) for thread in self.threads: reset_flag = vtypes.Land((fsm.state == fsm.current), (tid == thread.tid)) thread.fsm._set_index(thread.end_state) if thread.called is not None: thread.fsm.If(reset_flag)(thread.called(0)) thread.fsm.goto_from(thread.end_state, thread.start_state, reset_flag) thread._set_index(thread.start_state) return 0
def visit_Land(self, node): left = self.visit(node.left) right = self.visit(node.right) return vtypes.Land(left, right)
def _synthesize_run_fsm(self, parent_fsm, args, kwargs, cond=None): start_flag = (parent_fsm.state == parent_fsm.current) if self.called is None: self.called = self.m.Reg('_'.join(['', self.name, 'called']), initval=0) if cond is not None: self.fsm.If(cond) self.fsm.If(start_flag)(self.called(1)) functions = self._get_functions() cvisitor = compiler.CompileVisitor(self.m, self.name, self.clk, self.rst, self.fsm, functions, self.intrinsic_functions, self.intrinsic_methods, self.start_frame, datawidth=self.datawidth) text = textwrap.dedent(inspect.getsource(self.targ)) tree = ast.parse(text).body[0] # stack a new scope frame cvisitor.pushScope(ftype='call') used_args = [] # args args_code = [] for pos, arginfo in enumerate(tree.args.args): argname = ( arginfo.id if isinstance(arginfo, ast.Name) # python 2 else arginfo.arg) # python 3 # actual values can be assigned later in default value section args_code.append(argname) # regular args if pos < len(args): arg = args[pos] used_args.append(argname) if isinstance(arg, vtypes.numerical_types): # pass by value if argname not in self.args_dict: name = compiler._tmp_name('_'.join( ['', self.name, argname])) v = self.m.Reg(name, self.datawidth, initval=0, signed=True) cvisitor.scope.addVariable(argname, v) self.args_dict[argname] = v else: v = self.args_dict[argname] # binding if cond is not None: self.fsm.If(cond) self.fsm.If(start_flag)(v(arg)) else: # pass by reference if argname not in self.args_dict: cvisitor.scope.addVariable(argname, arg) self.args_dict[argname] = arg elif id(self.args_dict[argname]) == id(arg): pass else: raise ValueError( 'same object must be passed for non-numeric argument' ) # variable length args if tree.args.vararg is None and len(args) > len(tree.args.args): raise TypeError('takes %d positional arguments but %d were given' % (len(tree.args.args), len(args))) if tree.args.vararg is not None and not self.vararg_set: baseobj = tree.args.vararg varargname = ( baseobj.id if isinstance(baseobj, ast.Name) # python 2 else baseobj.arg) # python 3 cvisitor.scope.addVariable(varargname, self.vararg_regs) if len(args) > len(tree.args.args): used_args.append(varargname) raise ValueError( 'variable length argument is not supported in dynamic thread execution' ) #num_vararg_vars = len(args) - len(tree.args.args) # if num_vararg_vars > len(self.vararg_regs): # for i in range(num_vararg_vars - len(self.vararg_regs)): # name = compiler._tmp_name('_'.join(['', self.name, varargname])) # v = self.m.Reg(name, self.datawidth, initval=0, signed=True) # self.vararg_regs.append(v) # args_code.append(varargname) # for i, arg in enumerate(args[-num_vararg_vars:]): # if not isinstance(arg, vtypes.numerical_types): # raise TypeError('variable length argument support no non-numeric values') # v = self.vararg_regs[i] # # binding # if cond is not None: # self.fsm.If(cond) # self.fsm.If(start_flag)( # v(arg) # ) # kwargs kwargs_code = [] for argname, arg in sorted(kwargs.items(), key=lambda x: x[0]): if argname in used_args: raise TypeError("got multiple values for argument '%s'" % argname) used_args.append(argname) if isinstance(arg, vtypes.numerical_types): # pass by value if argname not in self.args_dict: name = compiler._tmp_name('_'.join( ['', self.name, argname])) v = self.m.Reg(name, self.datawidth, initval=0, signed=True) cvisitor.scope.addVariable(argname, v) self.args_dict[argname] = v else: v = self.args_dict[argname] # binding if cond is not None: self.fsm.If(cond) self.fsm.If(start_flag)(v(arg)) else: # pass by reference if argname not in self.args_dict: cvisitor.scope.addVariable(argname, arg) self.args_dict[argname] = arg elif id(self.args_dict[argname]) == id(arg): pass else: raise ValueError( 'same object must be passed for non-numeric argument') kwargs_code.append('{}={}'.format(key, key)) # defaults defaults_size = len(tree.args.defaults) if defaults_size > 0: for arg, val in zip(tree.args.args[-defaults_size:], tree.args.defaults): argname = ( arg.id if isinstance(arg, ast.Name) # python 2 else arg.arg) # python 3 if argname not in self.args_dict: name = compiler._tmp_name('_'.join( ['', self.name, argname])) v = self.m.Reg(name, self.datawidth, initval=0, signed=True) cvisitor.scope.addVariable(argname, v) self.args_dict[argname] = v else: v = self.args_dict[argname] if argname not in used_args: right = cvisitor.visit(val) # binding if cond is not None: self.fsm.If(cond) self.fsm.If(start_flag)(v(right)) c = start_flag if cond is not None: c = vtypes.Land(c, cond) self.fsm.goto_from(self.start_state, self.start_state + 1, c) self.fsm._set_index(self.start_state + 1) parent_fsm.goto_next() # if already synthesized if self.end_state is not None: return self.return_value # call AST args_text = ', '.join(args_code + kwargs_code) call_code = ''.join([self.targ.__name__, '(', args_text, ')']) _call_ast = ast.parse(call_code) # start visit self.return_value = cvisitor.visit(_call_ast.body[0].value) # clean-up jump conditions cvisitor.clearBreak() cvisitor.clearContinue() cvisitor.clearReturn() cvisitor.clearReturnVariable() # return to the previous scope frame cvisitor.popScope() return self.return_value