Пример #1
0
    def getFIFOInstOfNewTemplate(self, e_name: str, e_width: int, e_depth: int,
                                 pipeline_level: int):
        e_inst_list = self.e_name_to_ast_node[e_name]

        # use our FIFO template
        e_inst_list.module = 'fifo_almost_full'

        param_width = ast.ParamArg('DATA_WIDTH',
                                   ast.Rvalue(ast.IntConst(str(e_width))))
        param_depth = ast.ParamArg('DEPTH',
                                   ast.Rvalue(ast.IntConst(str(e_depth))))

        addr_bitwidth = int(math.log2(e_width) + 1)
        param_addr_width = ast.ParamArg(
            'ADDR_WIDTH', ast.Rvalue(ast.IntConst(str(addr_bitwidth))))

        # pipeline_level equals the required grace period
        param_grace_period = ast.ParamArg(
            'GRACE_PERIOD', ast.Rvalue(ast.IntConst(str(pipeline_level))))

        params = [
            param_width, param_depth, param_addr_width, param_grace_period
        ]
        e_inst_list.parameterlist = params

        for c in e_inst_list.instances:  # should only has 1 instance
            c.module = e_inst_list.module
            c.parameterlist = params

        return self.codegen.visit(e_inst_list)
Пример #2
0
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)
Пример #3
0
def gen_lat(path):
    clk = vast.Ioport(vast.Input('en'))
    q = vast.Ioport(vast.Output('Q'))
    d = vast.Ioport(vast.Input('D'))
    r = vast.Ioport(vast.Input('rst'))
    ports = vast.Portlist([clk, q, d, r])

    q_reg = vast.Identifier('reg Q = 0;')

    sens = []
    sens.append(vast.Sens(vast.Identifier('en'), type='level'))
    sens.append(vast.Sens(vast.Identifier('rst'), type='level'))
    sens.append(vast.Sens(vast.Identifier('D'), type='level'))

    senslist = vast.SensList(sens)

    assign_q = vast.NonblockingSubstitution(vast.Lvalue(vast.Identifier('Q')),
                                            vast.Rvalue(vast.Identifier('D')))

    blocks = []
    blocks.append(
        vast.IfStatement(
            vast.Identifier('rst'), vast.Identifier('Q <= 0;'),
            vast.IfStatement(vast.Identifier('en'), assign_q, None), None))

    statement = vast.Block(blocks)
    always = vast.Always(senslist, statement)

    items = []
    items.append(q_reg)
    items.append(always)
    ast = vast.ModuleDef("lat", None, ports, items)

    write_verilog(ast, 'lat.v', path)
Пример #4
0
 def visit_Localparam(self, node):
     name = node.name
     value = self.bind_visitor.visit(node.value)
     value = vast.Rvalue(value)
     width = self.make_width(node)
     signed = node.signed
     return vast.Localparam(name, value, width, signed)
Пример #5
0
 def visit_Assign(self, node):
     if not isinstance(node.statement, vtypes.Subst):
         raise TypeError("Assign expects Subst object.")
     left = self.bind_visitor.visit(node.statement.left)
     right = self.bind_visitor.visit(node.statement.right)
     lvalue = vast.Lvalue(left)
     rvalue = vast.Rvalue(right)
     return vast.Assign(lvalue, rvalue)
Пример #6
0
def _convert_hls_fifo_to_relay_station(node, e: Edge) -> None:
    node.module = 'relay_station'  # pipeline the FIFO

    width = ast.ParamArg('DATA_WIDTH', ast.Rvalue(ast.IntConst(str(e.width))))
    depth = ast.ParamArg(
        'DEPTH',
        ast.Rvalue(ast.IntConst(str(e.depth + e.added_depth_for_rebalance))))
    addr_width = ast.ParamArg('ADDR_WIDTH',
                              ast.Rvalue(ast.IntConst(str(e.addr_width))))
    level = ast.ParamArg('LEVEL',
                         ast.Rvalue(ast.IntConst(str(e.pipeline_level))))

    params = [width, depth, addr_width, level]
    node.parameterlist = params

    for c in node.instances:
        c.module = 'relay_station'
        c.parameterlist = params
Пример #7
0
def lower_next(done_stage: vast.IntConst, ns: NextState):
    """
        done_stage is the index of the final stage which just
        holds the all the values in the register.
    """
    # The computation is finished; transition to the done stage.
    if isinstance(ns, Done):
        return vast.Rvalue(done_stage)
    elif isinstance(ns, DirectNext):
        return vast.Rvalue(vast.IntConst(ns.state))
    elif isinstance(ns, CondNext):
        return vast.Cond(
            vast.Rvalue(vast.Identifier(ns.cond.name)),
            vast.IntConst(ns.on_true),
            vast.IntConst(ns.on_false),
        )
    else:
        raise ValueError("Malformed AST, expected next: %s" % ns.pretty())
Пример #8
0
 def visit_Subst(self, node):
     left = self.visit(node.left)
     right = self.visit(node.right)
     ldelay = vast.DelayStatement(self.visit(
         node.ldelay)) if node.ldelay else None
     rdelay = vast.DelayStatement(self.visit(
         node.rdelay)) if node.rdelay else None
     lvalue = vast.Lvalue(left)
     rvalue = vast.Rvalue(right)
     return vast.BlockingSubstitution(lvalue, rvalue, ldelay, rdelay)
Пример #9
0
 def visit_Localparam(self, node):
     name = node.name
     value = self.bind_visitor.visit(node.value)
     value = vast.Rvalue(value)
     width = (None if node.width is None else
              self.make_width_msb_lsb(node.width_msb, node.width_lsb)
              if node.width_msb is not None and node.width_lsb is not None
              else self.make_width(node.width))
     signed = node.signed
     return vast.Localparam(name, value, width, signed)
Пример #10
0
 def add_assign(self, lhs, rhs):
     '''Adds a new assignment'''
     assign = ast.Assign(ast.Lvalue(ast.Identifier(lhs)), ast.Rvalue(rhs))
     # find index to insert at
     insert_index = 0
     for i in range(len(self.module.items)):
         if isinstance(self.module.items[i], ast.Assign):
             insert_index = i + 1
     # insert the new assign node
     self.module.items = self.module.items[:insert_index] + (
         assign, ) + self.module.items[insert_index:]
Пример #11
0
def _convert_hls_fifo_to_autobridge_fifo_template(node, e: Edge) -> None:
    # TODO: remove the extra grace period from the FIFO template

    node.module = 'fifo_almost_full'  # pipeline the FIFO

    width = ast.ParamArg('DATA_WIDTH', ast.Rvalue(ast.IntConst(str(e.width))))
    depth = ast.ParamArg(
        'DEPTH',
        ast.Rvalue(ast.IntConst(str(e.depth + e.added_depth_for_rebalance))))
    addr_width = ast.ParamArg('ADDR_WIDTH',
                              ast.Rvalue(ast.IntConst(str(e.addr_width))))
    grace_period = ast.ParamArg('GRACE_PERIOD',
                                ast.Rvalue(ast.IntConst(str("0"))))

    params = [width, depth, addr_width, grace_period]
    node.parameterlist = params

    for c in node.instances:
        c.module = 'fifo_almost_full'
        c.parameterlist = params
Пример #12
0
def test():
    params = vast.Paramlist( [] )
    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) )
    items = [ vast.Assign( vast.Lvalue(vast.Identifier('led')),
                           vast.Rvalue(vast.IntConst('8'))) ]
    ast = vast.ModuleDef("top", params, ports, items)
    
    codegen = ASTCodeGenerator()
    rslt = codegen.visit(ast)
    
    print(rslt)
    assert(expected == rslt)
Пример #13
0
def addRelayStation(formator, node, edges_dict):
    # only considers fifo/rs instances
    if (not formator.isFIFOInstanceList(node)):
        return

    edge_name = formator.getFIFONameFromInstanceList(node)
    e = edges_dict[edge_name]

    if (e.mark):
        node.module = 'relay_station'

        width = ast.ParamArg('DATA_WIDTH',
                             ast.Rvalue(ast.IntConst(str(e.width))))
        depth = ast.ParamArg('DEPTH', ast.Rvalue(ast.IntConst(str(e.depth))))
        addr_width = ast.ParamArg('ADDR_WIDTH',
                                  ast.Rvalue(ast.IntConst(str(e.addr_width))))
        level = ast.ParamArg('LEVEL', ast.Rvalue(ast.IntConst(str(e.latency))))
        params = [width, depth, addr_width, level]

        node.parameterlist = params

        for c in node.instances:
            c.module = 'relay_station'
            c.parameterlist = params

        # print(f'[codegen] update rs to {edge_name} -> {node.module}')

    # replace the ad-hoc fifos by hls
    # add the depth used for balancing reconvergent paths
    else:
        node.module = 'fifo'
        new_depth = int(e.depth + e.additional_depth)
        new_addr_width = int(math.log2(new_depth) + 1)

        width = ast.ParamArg('DATA_WIDTH',
                             ast.Rvalue(ast.IntConst(str(e.width))))
        depth = ast.ParamArg('DEPTH', ast.Rvalue(ast.IntConst(str(new_depth))))
        addr_width = ast.ParamArg(
            'ADDR_WIDTH', ast.Rvalue(ast.IntConst(str(new_addr_width))))
        params = [width, depth, addr_width]

        node.parameterlist = params

        for c in node.instances:
            c.module = 'fifo'
            c.parameterlist = params
Пример #14
0
def gen_dff(path):
    clk = vast.Ioport(vast.Input('clk'))
    q = vast.Ioport(vast.Output('Q'))
    d = vast.Ioport(vast.Input('D'))
    ports = vast.Portlist([clk, q, d])

    q_reg = vast.Identifier('reg Q = 0;')

    sens = vast.Sens(vast.Identifier('clk'), type='posedge')
    senslist = vast.SensList([sens])

    assign_q = vast.NonblockingSubstitution(vast.Lvalue(vast.Identifier('Q')),
                                            vast.Rvalue(vast.Identifier('D')))

    statement = vast.Block([assign_q])
    always = vast.Always(senslist, statement)

    items = []
    items.append(q_reg)
    items.append(always)
    ast = vast.ModuleDef("dff", None, ports, items)

    write_verilog(ast, 'dff.v', path)
Пример #15
0
def lower_fsm(fsm: FSM):
    assert fsm.start_state == 0, "Starting state is not 0"
    zero = vast.IntConst(0)
    all_registers = [
        Register("a", 8),
        Register("b", 8),
        Register("tmp", 8),
        Register("_cond", 1),
    ]
    register_defs = [
        vast.Reg(
            reg.name,
            vast.Width(vast.IntConst(reg.width -
                                     1), zero) if reg.width - 1 != 0 else None)
        for reg in all_registers
    ]

    ports = vast.Portlist([
        vast.Ioport(vast.Input('clk')),
        # XXX(rachit): AST can't represent `output reg done`
        # so assign to a local register and use a wire.
        vast.Ioport(vast.Output('done')),
    ])
    done_state = max(fsm.actions.keys()) + 1
    done_reg = vast.Reg('done_out')
    hook_up_done = vast.Assign(
        vast.Lvalue(vast.Identifier('done')),
        vast.Rvalue(vast.Identifier('done_out')),
    )

    # Register to store the FSM state.
    fsm_reg_size = int(math.ceil(math.log2(done_state))) + 1
    fsm_reg = vast.Reg(name="fsm_reg",
                       width=vast.Width(vast.IntConst(fsm_reg_size - 1), zero))

    # Define all the registers.
    reg_decl = register_defs + [fsm_reg]

    # Define the initial process
    inits = vast.Initial(
        vast.Block([
            vast.BlockingSubstitution(
                vast.Lvalue(vast.Identifier(reg.name)),
                vast.Rvalue(vast.IntConst(0)),
            ) for reg in reg_decl
        ]))

    # Default case, assigns to the done register.
    done = vast.IntConst(done_state)
    default_case = vast.Case(cond=None,
                             statement=vast.Block([
                                 vast.NonblockingSubstitution(
                                     vast.Lvalue(vast.Identifier(reg.name)),
                                     vast.Rvalue(vast.Identifier(reg.name)),
                                 ) for reg in reg_decl
                             ] + [
                                 vast.NonblockingSubstitution(
                                     vast.Lvalue(vast.Identifier('done_out')),
                                     vast.Rvalue(vast.IntConst(1)))
                             ]))

    # Generate Case conditions for each transition.
    cases = [
        vast.Case([vast.IntConst(cond_val)],
                  lower_action(fsm_reg, done, action))
        for (cond_val, action) in fsm.actions.items()
    ]
    case_statement = vast.CaseStatement(comp=vast.Identifier(fsm_reg.name),
                                        caselist=cases + [default_case])
    always_ff = vast.Always(
        vast.SensList([vast.Sens(vast.Identifier('clk'), 'posedge')]),
        vast.Block([case_statement]))

    return vast.ModuleDef(name="main",
                          paramlist=vast.Paramlist([]),
                          portlist=ports,
                          items=reg_decl +
                          [done_reg, hook_up_done, inits, always_ff])
Пример #16
0
def lower_update(upd: Update):
    reg = upd.register.name
    return vast.NonblockingSubstitution(vast.Lvalue(vast.Identifier(reg)),
                                        vast.Rvalue(lower_expr(upd.expr)))