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
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
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
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]
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]
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
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
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
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
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
def buildRuleMatchResponse(self): rname = "rl_handle_response" cond = "interruptStatus" stmt = self.buildRuleMatchResponseStmt() rule = ast.Rule(rname, cond, stmt) return rule