def test(): datawid = vast.Parameter( 'DATAWID', vast.Rvalue(vast.IntConst('32')) ) params = vast.Paramlist( [datawid] ) clk = vast.Ioport( vast.Input('CLK') ) rst = vast.Ioport( vast.Input('RST') ) width = vast.Width( vast.IntConst('7'), vast.IntConst('0') ) led = vast.Ioport( vast.Output('led', width=width) ) ports = vast.Portlist( [clk, rst, led] ) width = vast.Width( vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('1')), vast.IntConst('0') ) count = vast.Reg('count', width=width) assign = vast.Assign( vast.Lvalue(vast.Identifier('led')), vast.Rvalue( vast.Partselect( vast.Identifier('count'), # count vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('1')), # [DATAWID-1: vast.Minus(vast.Identifier('DATAWID'), vast.IntConst('8'))))) # :DATAWID-8] sens = vast.Sens(vast.Identifier('CLK'), type='posedge') senslist = vast.SensList([ sens ]) assign_count_true = vast.NonblockingSubstitution( vast.Lvalue(vast.Identifier('count')), vast.Rvalue(vast.IntConst('0'))) if0_true = vast.Block([ assign_count_true ]) # (count + 1) * 2 count_plus_1 = vast.Plus(vast.Identifier('count'), vast.IntConst('1')) cp1_times_2 = vast.Times(count_plus_1, vast.IntConst('2')) cp1t2_plus_1 = vast.Plus(cp1_times_2, vast.IntConst('1')) assign_count_false = vast.NonblockingSubstitution( vast.Lvalue(vast.Identifier('count')), vast.Rvalue(cp1t2_plus_1)) if0_false = vast.Block([ assign_count_false ]) if0 = vast.IfStatement(vast.Identifier('RST'), if0_true, if0_false) statement = vast.Block([ if0 ]) always = vast.Always(senslist, statement) items = [] items.append(count) items.append(assign) items.append(always) ast = vast.ModuleDef("top", params, ports, items) codegen = ASTCodeGenerator() rslt = codegen.visit(ast) print(rslt) assert(expected == rslt)
def expose_internal_scheduling_signals(self, num_rules_per_module=None, scheduling_order=None, add_force_fire=False): # if schedule isn't provided, assume rules first then modules if scheduling_order is None: scheduling_order = [ 'RL_' + x for x in self.get_rules_in_scheduling_order() ] + ['MODULE_' + x for x, y in self.get_submodules()] instance_to_module = {x: y for x, y in self.get_submodules()} can_fires = [] will_fires = [] # compute total number of bits total_num_bits = 0 for name in scheduling_order: if name.startswith('RL_'): total_num_bits += 1 elif name.startswith('MODULE_'): instance_name = name[len('MODULE_'):] module_name = instance_to_module[instance_name] if num_rules_per_module is None: continue if module_name not in num_rules_per_module: continue num_submodule_rules = num_rules_per_module[module_name] if num_submodule_rules == 0: continue total_num_bits += num_submodule_rules # now add the signals curr_bit_index = 0 for name in scheduling_order: if name.startswith('RL_'): self.add_decls('BLOCK_FIRE_' + name, ast.Wire) if add_force_fire: self.add_decls('FORCE_FIRE_' + name, ast.Wire) # definition of BLOCK_FIRE and FORCE_FILE assign = self.get_assign('WILL_FIRE_' + name) if add_force_fire: new_rhs = ast.Or( ast.Identifier('FORCE_FIRE_' + name), ast.And(ast.Unot(ast.Identifier('BLOCK_FIRE_' + name)), assign.right.var)) else: new_rhs = ast.And( ast.Unot(ast.Identifier('BLOCK_FIRE_' + name)), assign.right.var) assign.right.var = new_rhs # definition of BLOCK_FIRE_* and FORCE_FIRE_* signals from top-level BLOCK_FIRE and FORCE_FIRE if total_num_bits == 1: self.add_assign('BLOCK_FIRE_' + name, ast.Identifier('BLOCK_FIRE')) if add_force_fire: self.add_assign('FORCE_FIRE_' + name, ast.Identifier('FORCE_FIRE')) else: self.add_assign( 'BLOCK_FIRE_' + name, ast.Partselect(ast.Identifier('BLOCK_FIRE'), ast.IntConst(curr_bit_index), ast.IntConst(curr_bit_index))) if add_force_fire: self.add_assign( 'FORCE_FIRE_' + name, ast.Partselect(ast.Identifier('FORCE_FIRE'), ast.IntConst(curr_bit_index), ast.IntConst(curr_bit_index))) curr_bit_index += 1 can_fires.append(ast.Identifier('CAN_FIRE_' + name)) will_fires.append(ast.Identifier('WILL_FIRE_' + name)) elif name.startswith('MODULE_'): instance_name = name[len('MODULE_'):] module_name = instance_to_module[instance_name] if num_rules_per_module is None: continue if module_name not in num_rules_per_module: continue num_submodule_rules = num_rules_per_module[module_name] if num_submodule_rules == 0: continue instance = self.get_instance(instance_name) for signal_type in [ 'CAN_FIRE', 'WILL_FIRE', 'BLOCK_FIRE', 'FORCE_FIRE' ]: if signal_type == 'FORCE_FIRE' and not add_force_fire: continue # declarations of all FIRE signals for the submodule self.add_decls(signal_type + '_' + name, ast.Wire, width=num_submodule_rules) # connection of all FIRE signals to the submodule # this assumes the submodule has ports named CAN_FIRE, WILL_FIRE, BLOCK_FIRE, and if add_force_fire is true, FORCE_FIRE instance.portlist += (ast.PortArg( signal_type, ast.Identifier(signal_type + '_' + name)), ) # assignments of BLOCK_FIRE_* and FORCE_FIRE_* signals from top-level BLOCK_FIRE and FORCE_FIRE lsb = curr_bit_index msb = curr_bit_index + num_submodule_rules - 1 curr_bit_index += num_submodule_rules if total_num_bits == 1: self.add_assign('BLOCK_FIRE_' + name, ast.Identifier('BLOCK_FIRE')) if add_force_fire: self.add_assign('FORCE_FIRE_' + name, ast.Identifier('FORCE_FIRE')) else: self.add_assign( 'BLOCK_FIRE_' + name, ast.Partselect(ast.Identifier('BLOCK_FIRE'), ast.IntConst(msb), ast.IntConst(lsb))) if add_force_fire: self.add_assign( 'FORCE_FIRE_' + name, ast.Partselect(ast.Identifier('FORCE_FIRE'), ast.IntConst(msb), ast.IntConst(lsb))) can_fires.append(ast.Identifier('CAN_FIRE_' + name)) will_fires.append(ast.Identifier('WILL_FIRE_' + name)) elif name.startswith('METH_'): raise ValueError( '"METH_" scheduling signals are not supported yet') else: raise ValueError('unexpected entry "%s" in scheduling_order' % name) if total_num_bits != 0: # new ports self.add_ports(['CAN_FIRE', 'WILL_FIRE', 'BLOCK_FIRE']) if add_force_fire: self.add_ports(['FORCE_FIRE']) self.add_decls('CAN_FIRE', ast.Output, width=total_num_bits) self.add_decls('WILL_FIRE', ast.Output, width=total_num_bits) self.add_decls('BLOCK_FIRE', ast.Input, width=total_num_bits) if add_force_fire: self.add_decls('FORCE_FIRE', ast.Input, width=total_num_bits) self.add_decls('CAN_FIRE', ast.Wire, width=total_num_bits) self.add_decls('WILL_FIRE', ast.Wire, width=total_num_bits) # connect CAN_FIRE and WILL_FIRE can_fires.reverse() will_fires.reverse() self.add_assign('CAN_FIRE', ast.Concat(can_fires)) self.add_assign('WILL_FIRE', ast.Concat(will_fires)) return total_num_bits
def visit_Slice(self, node): var = self.visit(node.var) msb = self.visit(node.msb) lsb = self.visit(node.lsb) return vast.Partselect(var, msb, lsb)