예제 #1
0
    def buildRuleActionResponse(self):
        TMP1 = "let v <- toGet(bbRspFifo[readyChannel]).get;"
        TMP2 = "let meta <- toGet(metadata_ff).get;"
        TMP3 = "tagged %(name)sRspT {%(field)s}"
        TMP4 = "MetadataResponse rsp = tagged %(name)s%(action)sRspT {pkt: pkt, meta: meta};"
        TMP5 = "tx_info_%(name)s.enq(rsp);"
        TMP6 = "meta.%(name)s = tagged Valid %(name)s;"

        stmt = []
        case_stmt = ast.Case("v")

        for idx, action in enumerate(self.actions):
            basic_block = self.basic_block_map[action]
            fields = basic_block.response.build_match_expr()
            action_stmt = []
            for field in basic_block.response.get_members():
                action_stmt.append(ast.Template(TMP6 % {"name": field}))
            action_stmt.append(
                ast.Template(TMP4 % {
                    "name": CamelCase(self.name),
                    "action": CamelCase(action)
                }))
            action_stmt.append(ast.Template(TMP5 % {"name": "metadata"}))

            action = TMP3 % {"name": CamelCase(action), "field": fields}
            case_stmt.casePatStmt[action] = action_stmt

        stmt.append(ast.Template(TMP1))
        stmt.append(ast.Template(TMP2))
        stmt.append(case_stmt)

        rname = "rl_handle_action_response"
        cond = "interruptStatus"
        rule = ast.Rule(rname, cond, stmt)
        return rule
    def build_rule_parse_done(self):
        TMP1 = "let %(ktype)s <- toGet(%(ktype)s_out_ff).get;"
        stmt = []
        stmt += [ast.Template("MetadataT meta = defaultValue;")]
        pdict = {}
        pdict['ktype'] = set()
        for idx, s in enumerate(self.states.values()):
            keys = []
            for k in s.transition_keys:
                if k['type'] == 'lookahead':
                    print "WARNING: lookahead type not handled"
                    continue
                keys.append("%s.%s" % (k['value'][0], k['value'][1]))
                pdict['ktype'].add(k['value'][0])
            pdict['field'] = ",".join(keys)
        for ktype in pdict['ktype']:
            stmt += [ast.Template(TMP1, {'ktype': ktype})]

        for ktype in pdict['ktype']:
            if ktype in  self.metadata:
                stmt_if = []
                for f in self.metadata[ktype]:
                    stmt_if.append(ast.Template("meta.%(metafield)s = tagged Valid fromMaybe(?, %(ktype)s).%(field)s;" % {'metafield': "%s$%s" % (ktype, f[1]), 'ktype': ktype, 'field': f[1]}))
                stmt += [ast.If("isValid(%s)" % ktype, stmt_if)]

        stmt += [ast.Template("dbprint(3, $format(\"parse_done\"));")]
        stmt += [ast.Template("meta_in_ff.enq(meta);")]

        rcond = '(w_parse_done)' % pdict
        rname = 'rl_parse_done' % pdict
        rule = ast.Rule(rname, rcond, stmt, [])
        return [rule]
 def buildRules(self):
     TMP1 = "%(name)s_req_ff.notEmpty"
     TMP2 = "%(name)s_rsp_ff.notEmpty"
     rules = []
     rname = "default_next_state"
     cond = TMP1 % ({"name": "default", "type": "Default"})
     stmt = self.buildDefaultRuleStmt(self.init_table)
     rule = ast.Rule(rname, cond, stmt)
     rules.append(rule)
     for t in self.tables.values():
         rname = t.name + "_next_state"
         cond = TMP2 % ({"name": t.name, "type": CamelCase(t.name)})
         stmt = self.buildTableRuleStmt(t.name)
         rule = ast.Rule(rname, cond, stmt)
         rules.append(rule)
     return rules
예제 #4
0
 def buildLoopback(self):
     TMP1 = "tagged %(type)s {%(field)s}"
     TMP2 = "let v = rx_info_prev_control_state.first;"
     TMP3 = "rx_info_prev_control_state.deq;"
     TMP4 = "BBResponse rsp = tagged %(type)s {pkt: pkt};"
     TMP5 = "tx_info_prev_control_state.enq(rsp);"
     rules = []
     stmt = []
     cname = CamelCase(self.name)
     ctype = "%sReqT"%(cname)
     pdict = {"type": ctype, "field": self.request.build_match_expr()}
     casePatStmts = []
     stmt.append(ast.Template(TMP2))
     stmt.append(ast.Template(TMP3))
     ctype = ast.Template(TMP1, pdict)
     case_stmt = ast.Case("v")
     case_stmt.casePatStmt[ctype] = casePatStmts
     rsp_prefix = CamelCase(self.name)
     casePatStmts.append(ast.Template(TMP4, {"type": "%sRspT"%(rsp_prefix)} ))
     casePatStmts.append(ast.Template(TMP5, {"name": self.name}))
     stmt.append(case_stmt)
     rname = self.name + "_loopback"
     rule = ast.Rule(rname, [], stmt)
     rules.append(rule)
     return rules
예제 #5
0
 def rule_state_next(self, state, width):
     tmpl = []
     tmpl.append("deparse_state_ff.enq(StateDeparse%s);" % CamelCase(state))
     tmpl.append("fetch_next_header(%d);" % width)
     rname = "rl_deparse_%s_next" % (state.translate(None, "[]"))
     rcond = "w_deparse_%s" % (state.translate(None, "[]"))
     stmt = apply_pdict(tmpl, {})
     rule = ast.Rule(rname, rcond, stmt)
     return rule
예제 #6
0
 def rule_state_send(self, state, width):
     tmpl = []
     tmpl.append("succeed_and_next(%d);" % width)
     tmpl.append("deparse_state_ff.deq;")
     rname = "rl_deparse_%s_send" % (state.translate(None, "[]"))
     rcond = "(deparse_state_ff.first == StateDeparse%s) && (rg_buffered[0] >= %d)" % (
         CamelCase(state), width)
     stmt = apply_pdict(tmpl, {})
     rule = ast.Rule(rname, rcond, stmt)
     return rule
    def build_rule_state_extract(self, state):
        tmpl = []
        tmpl.append("let data = rg_tmp[0];")
        tmpl.append("if (isValid(data_ff.first)) begin")
        tmpl.append("  data_ff.deq;")
        tmpl.append("  data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];")
        tmpl.append("end")
        tmpl.append("report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, data);")
        TMP = "let %(header)s = extract_%(ktype)s(truncate(data));"
        tmpl2 = []
        tmpl2.append("compute_next_state_%(name)s(%(field)s);")
        tmpl2.append("rg_tmp[0] <= zeroExtend(data >> %(len)s);")
        tmpl2.append("succeed_and_next(%(len)s);")
        tmpl2.append("dbprint(3, $format(\"extract %%s\", \"%(name)s\"));")
        tmpl2.append("parse_state_ff.deq;")

        TMP3 = "%(header)s_out_ff.enq(tagged Valid %(header)s);"

        pdict = {}
        pdict['name'] = state.name
        pdict['CurrState'] = 'State%s' % (CamelCase(state.name))
        pdict['len'] = state.len
        keys = []
        pdict['ktype'] = set()
        for k in state.transition_keys:
            if k['type'] == 'lookahead':
                print "WARNING: lookahead type not handled"
                continue
            header_type = GetHeaderType(k['value'][0])
            header = k['value'][0]
            keys.append("%s.%s" % (header, k['value'][1]))
            pdict['ktype'].add((header, header_type))
        pdict['field'] = ",".join(keys)

        stmt = apply_pdict(tmpl, pdict)
        for hdr, ktype in pdict['ktype']:
            stmt += [ast.Template(TMP, {'header': hdr, 'ktype': ktype})]
        stmt += apply_pdict(tmpl2, pdict)
        for hdr, ktype in pdict['ktype']:
            stmt += [ast.Template(TMP3, {'header': hdr, 'ktype': ktype})]

        # build expression
        setexpr = GetExpressionInState(state.name)
        if setexpr[2] != None and setexpr[1] != None:
            dst = "".join(setexpr[1])+"[0]"
            src = "".join(setexpr[2])
            stmt += [ast.Template(dst + " <= " + src.replace("0x", "'h") + ";")]

        rcond = '(parse_state_ff.first == %(CurrState)s) && (rg_buffered[0] >= %(len)s)' % pdict
        rname = 'rl_%(name)s_extract' % pdict
        attr = ['fire_when_enabled']
        rule = ast.Rule(rname, rcond, stmt, attr)
        return [rule]
예제 #8
0
 def rule_state_load(self, state, width):
     tmpl = []
     tmpl.append(
         "rg_tmp[0] <= zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];"
     )
     tmpl.append(
         "UInt#(NumBytes) n_bytes_used = countOnes(mask_this_cycle);")
     tmpl.append("UInt#(NumBits) n_bits_used = cExtend(n_bytes_used) << 3;")
     tmpl.append("move_buffered_amt(cExtend(n_bits_used));")
     rname = "rl_deparse_%s_load" % (state.translate(None, "[]"))
     rcond = "(deparse_state_ff.first == StateDeparse%s) && (rg_buffered[0] < %d)" % (
         CamelCase(state), width)
     stmt = apply_pdict(tmpl, {})
     rule = ast.Rule(rname, rcond, stmt)
     return rule
 def build_rule_state_load(self, state):
     tmpl = []
     tmpl.append("data_ff.deq;")
     tmpl.append("let data = zeroExtend(data_this_cycle) << rg_shift_amt[0] | rg_tmp[0];")
     tmpl.append("rg_tmp[0] <= zeroExtend(data);")
     tmpl.append("move_shift_amt(%d);" % (config.DP_WIDTH))
     pdict = {}
     pdict['name'] = state.name
     pdict['CurrState'] = 'State%s' % (CamelCase(state.name))
     pdict['len'] = state.len
     stmt = apply_pdict(tmpl, pdict)
     expr = "isValid(data_ff.first)"
     ifstmt = []
     ifstmt.append(ast.Template("report_parse_action(parse_state_ff.first, rg_buffered[0], data_this_cycle, rg_tmp[0]);"))
     ifstmt.append(ast.If(expr, stmt))
     rcond = '(parse_state_ff.first == %(CurrState)s) && (rg_buffered[0] < %(len)s)' % pdict
     attr = ['fire_when_enabled']
     rule = ast.Rule('rl_%(name)s_load' % pdict, rcond, ifstmt, attr)
     return [rule]
예제 #10
0
 def buildRuleMatchRequest(self):
     TMP1 = "let data = rx_info_%(name)s.first;"
     TMP2 = "let meta = data.meta;"
     TMP8 = "let pkt = data.pkt;"
     TMP3 = "%(type)s req = %(type)s {%(field)s};"
     TMP4 = "matchTable.lookupPort.request.put(pack(req));"
     TMP5 = "let %(name)s = fromMaybe(?, meta.%(name)s);"
     TMP6 = "{%(field)s}"
     TMP7 = "rx_info_%(name)s.deq;"
     rname = "rl_handle_request"
     stmt = []
     stmt.append(ast.Template(TMP1, {"name": "metadata"}))
     stmt.append(ast.Template(TMP7, {"name": "metadata"}))
     stmt.append(ast.Template(TMP2))
     stmt.append(ast.Template(TMP8))
     keys = self.buildMatchKey()
     fields = []
     total_width = 0
     for k in keys:
         if type(k) != list:
             total_width += 1
             name = 'valid_%s' % k
             fields.append("%s: %s" % (p4name(name), p4name(name)))
         else:
             width = GetFieldWidth(k)
             total_width += width
             stmt.append(ast.Template(TMP5, {"name": p4name(k)}))
             fields.append("%s: %s" % (p4name(k), p4name(k)))
     if (total_width % 9):
         fields.insert(0, "padding: 0")
     stmt.append(
         ast.Template(TMP3, {
             "type": self.req_name,
             "field": ", ".join(fields)
         }))
     stmt.append(ast.Template(TMP4))
     stmt.append(ast.Template("packet_ff.enq(pkt);"))
     stmt.append(ast.Template("metadata_ff[0].enq(meta);"))
     cond = []
     rule = ast.Rule(rname, cond, stmt)
     return rule
예제 #11
0
 def buildHandleResponse(self):
     TMP1 = "let pkt <- toGet(curr_packet_ff).get;"
     TMP2 = "BBResponse rsp = tagged %(type)s {%(field)s};"
     TMP3 = "tx_info_prev_control_state.enq(rsp);"
     rules = []
     stmt = []
     rname = self.name + "_response"
     for p in self.primitives:
         stmt += p.buildResponse()
     # optimized bypass register
     # field must include bypass register
     stmt.append(ast.Template(TMP1))
     for p in self.primitives:
         stmt += p.readTempReg(self.json_dict)
     rsp_prefix = CamelCase(self.name)
     stmt.append(ast.Template(TMP2, {"type": "%sRspT"%(rsp_prefix),
                                     "field": self.response.build_case_expr()}))
     stmt.append(ast.Template(TMP3, {"name": self.name}))
     rule = ast.Rule(rname, [], stmt)
     rules.append(rule)
     return rules
예제 #12
0
    def buildRuleExecuteAction(self):
        TMP1 = "let rsp <- matchTable.lookupPort.response.get;"
        TMP2 = "let pkt <- toGet(packet_ff).get;"
        TMP3 = "let meta <- toGet(metadata_ff[0]).get;"
        TMP4 = "%(type)s resp = unpack(data);"
        TMP7 = "metadata_ff[1].enq(meta);"

        TMP8 = "BBRequest req = tagged %(type)sReqT {%(field)s};"
        TMP9 = "bbReqFifo[%(id)s].enq(req); //FIXME: replace with RXTX."

        stmt = []
        stmt.append(ast.Template(TMP1))
        stmt.append(ast.Template(TMP2))
        stmt.append(ast.Template(TMP3))
        case_stmt = ast.Case("resp._action")

        for idx, action in enumerate(self.actions):
            basic_block = self.basic_block_map[action]
            fields = basic_block.request.build_case_expr()
            action_stmt = []
            action_stmt.append(
                ast.Template(TMP8, {
                    "type": CamelCase(action),
                    "field": fields
                }))
            action_stmt.append(ast.Template(TMP9, {"id": idx}))
            _action = action.lstrip('_').upper()
            case_stmt.casePatStmt[_action] = action_stmt

        if_stmt = ast.If("rsp matches tagged Valid .data", [])
        if_stmt.stmt.append(ast.Template(TMP4, {"type": self.rsp_name}))
        if_stmt.stmt.append(case_stmt)
        if_stmt.stmt.append(ast.Template("// forward metadata to next stage."))
        if_stmt.stmt.append(ast.Template(TMP7))
        stmt.append(if_stmt)

        rname = "rl_handle_execute"
        cond = []
        rule = ast.Rule(rname, cond, stmt)
        return rule
예제 #13
0
    def buildRuleActionRequest(self):
        TMP1 = "let data = rx_info_%(name)s.first;"
        TMP2 = "rx_info_%(name)s.deq;"
        TMP3 = "let meta = data.meta;"
        TMP4 = "let pkt = data.pkt;"
        TMP5 = "let %(field)s = fromMaybe(?, meta.%(field)s);"

        TMP8 = "BBRequest req = tagged %(type)sReqT {%(field)s};"
        TMP9 = "bbReqFifo[%(id)s].enq(req); //FIXME: replace with RXTX."

        stmt = []
        stmt.append(ast.Template(TMP1, {"name": "metadata"}))
        stmt.append(ast.Template(TMP2, {"name": "metadata"}))
        stmt.append(ast.Template(TMP3))
        stmt.append(ast.Template(TMP4))
        stmt.append(ast.Template("packet_ff.enq(pkt);"))
        stmt.append(ast.Template("metadata_ff.enq(meta);"))

        for idx, action in enumerate(self.actions):
            basic_block = self.basic_block_map[action]
            for f in basic_block.request.members:
                stmt.append(ast.Template(TMP5, {"field": p4name(f)}))

        for idx, action in enumerate(self.actions):
            basic_block = self.basic_block_map[action]
            fields = basic_block.request.build_case_expr()
            stmt.append(
                ast.Template(TMP8, {
                    "type": CamelCase(action),
                    "field": fields
                }))
            stmt.append(ast.Template(TMP9, {"id": idx}))

        rname = "rl_handle_action_request"
        cond = []
        rule = ast.Rule(rname, cond, stmt)
        return rule
예제 #14
0
    def buildHandleRequest(self):
        TMP1 = "tagged %(type)s {%(field)s}"
        TMP2 = "let v = rx_info_prev_control_state.first;"
        TMP3 = "rx_info_prev_control_state.deq;"
        rules = []
        stmt = []
        rname = self.name + "_request"
        cname = CamelCase(self.name)
        ctype = "%sReqT"%(cname)
        pdict = {"type": ctype, "field": self.request.build_match_expr()}
        casePatStmts = []
        casePatStmts.append(ast.Template("cpu.run();"))
        casePatStmts += self.buildPacketFF()

        stmt.append(ast.Template(TMP2))
        stmt.append(ast.Template(TMP3))

        case_stmt = ast.Case("v")
        ctype = ast.Template(TMP1, pdict)
        case_stmt.casePatStmt[ctype] = casePatStmts
        stmt.append(case_stmt)
        rule = ast.Rule(rname, 'cpu.not_running()', stmt)
        rules.append(rule)
        return rules
        def build_rule_state_transition(cregIdx, state, next_state):
            # skip duplicated transition rule
            transition = "%s_%s" % (state.name, next_state.name)
            if transition in self.state_transitions_generated:
                return
            self.state_transitions_generated.add(transition)

            # forward transition
            tmpl_forward_flow = []
            tmpl_forward_flow.append("parse_state_ff.enq(%(NextState)s);")
            tmpl_forward_flow.append("dbprint(3, $format(\"%%s -> %%s\", \"%(name)s\", \"%(next_state)s\"));")
            tmpl_forward_flow.append("fetch_next_header%(cregIdx)s(%(length)s);")

            # back to start
            tmpl_to_start = []
            tmpl_to_start.append("parse_done[0] <= True;")
            tmpl_to_start.append("w_parse_done.send();")
            tmpl_to_start.append("dbprint(3, $format(\"%%s -> %%s\", \"%(name)s\", \"%(next_state)s\"));")
            tmpl_to_start.append("fetch_next_header%(cregIdx)s(0);")

            # transition with lookahead
            tmpl_lookahead = []
            tmpl_lookahead.append("Vector#(512, Bit#(1)) buffer = unpack(rg_tmp[1]);")
            tmpl_lookahead.append("Bit#(%(lookahead)s) lookahead = pack(takeAt(0, buffer));")
            tmpl_lookahead.append("dbprint(3, $format(\"look ahead %%h, %%h\", lookahead, rg_tmp[1]));")
            tmpl_lookahead.append("compute_next_state_%(next_state)s(%(field)s);")
            tmpl_lookahead.append("dbprint(3, $format(\"counter\", %(field)s ));")
            tmpl_lookahead.append("dbprint(3, $format(\"%%s -> %%s\", \"%(name)s\", \"%(next_state)s\"));")
            tmpl_lookahead.append('fetch_next_header%(cregIdx)s(0);')

            pdict = {}
            pdict['name'] = state.name
            pdict['CurrState'] = "State%s" % (CamelCase(state.name))
            pdict['next_state'] = next_state.name
            pdict['NextState'] = "State%s" % (CamelCase(next_state.name))
            pdict['length'] = GetHeaderWidthInState(next_state.name)
            pdict['cregIdx'] = cregIdx
            pdict['lookahead'] = 8 #FIXME
            keys = []
            for k in next_state.transition_keys:
                if k['type'] == 'lookahead':
                    keys.append("lookahead")
                else:
                    field = k['value'][0]
                    if field[0].isupper():
                        field = field[0].lower() + field
                    keys.append("%s$%s[1]" % (field, k['value'][1]))
            pdict['field'] = ", ".join(keys)

            #print state.name, state.state_type
            if next_state.id == 0:
                stmt = apply_pdict(tmpl_to_start, pdict)
            elif state.id > next_state.id and state.state_type == ParseState.EMPTY:
                stmt = apply_pdict(tmpl_lookahead, pdict)
            elif next_state.state_type == ParseState.EMPTY:
                stmt = apply_pdict(tmpl_lookahead, pdict)
            else:
                stmt = apply_pdict(tmpl_forward_flow, pdict)
            rname = 'rl_%(name)s_%(next_state)s' % pdict
            rcond = "(w_%(name)s_%(next_state)s)" % pdict
            rule = ast.Rule(rname, rcond, stmt)
            return rule
예제 #16
0
 def buildRuleMatchResponse(self):
     rname = "rl_handle_response"
     cond = "interruptStatus"
     stmt = self.buildRuleMatchResponseStmt()
     rule = ast.Rule(rname, cond, stmt)
     return rule