def buildRuleMatchResponseStmt(self): TMP1 = "let v <- toGet(bbRspFifo[readyChannel]).get;" TMP2 = "let meta <- toGet(metadata_ff[1]).get;" TMP3 = "tagged %(name)sRspT {%(field)s}" TMP4 = "%(ty_metadata)s rsp = tagged %(name)s {pkt: pkt, meta: meta};" TMP5 = "tx_info_%(name)s.enq(rsp);" TMP6 = "meta.%(mname)s = tagged Valid %(mname)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.members: mname = p4name(field) action_stmt.append(ast.Template(TMP6 % {"mname": mname})) tagname = "%s%sRspT" % (CamelCase(self.name), CamelCase(action)) action_stmt.append( ast.Template( TMP4 % { "name": tagname, "ty_metadata": CamelCase(self.name) + "Response" })) 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) return stmt
def _add_defaults(self, fields): self.stmt.append(ast.Template(STRUCT_DEFAULT, {"name": CamelCase(self.name)})) self.stmt.append(ast.Template(STRUCT_MASK, {"name": CamelCase(self.name)})) _sum = 0 for _, l in fields: _sum += l self.stmt.append(ast.Template(EXTRACT_TEMP, {"name": CamelCase(self.name), "lname": self.name, "width": _sum}))
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 buildConnection(self): TMP1 = "Vector#(numClients, Server#(MetadataRequest, MetadataResponse)) mds = replicate(toServer(default_req_ff, default_rsp_ff));" TMP2 = "mkConnection(mds, mdc);" stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2)) return stmt
def build_intf_decl_verbosity(self): stmt = [] stmt.append( ast.Template("method Action set_verbosity (int verbosity);")) stmt.append(ast.Template(" cf_verbosity <= verbosity;")) stmt.append(ast.Template("endmethod")) return stmt
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 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 build_intf_decl_verbosity(self): stmt = [] stmt.append(ast.Template("method Action set_verbosity (int verbosity);")) stmt.append(ast.Template(" cf_verbosity <= verbosity;")) if len(self.primitives) != 0: stmt.append(ast.Template(" cpu.set_verbosity(verbosity);")) stmt.append(ast.Template(" imem.set_verbosity(verbosity);")) stmt.append(ast.Template("endmethod")) return stmt
def build_rules(self): stmt = [] stmt.append(ast.Template('`ifdef DEPARSER_RULES\n')) for idx, s in enumerate(self.deparse_states): stmt.append(self.rule_state_next(s, GetHeaderWidth(s))) stmt.append(self.rule_state_load(s, GetHeaderWidth(s))) stmt.append(self.rule_state_send(s, GetHeaderWidth(s))) stmt.append(ast.Template('`endif // DEPARSER_RULES\n')) return stmt
def build_state(self): stmt = [] stmt.append(ast.Template("`ifdef DEPARSER_STATE\n")) for idx, state in enumerate(self.deparse_states): stmt.append( ast.Template( "PulseWire w_deparse_%(name)s <- mkPulseWire();\n", {'name': state.translate(None, "[]")})) stmt.append(ast.Template("`endif // DEPARSER_STATE\n")) return stmt
def funct_compute_next_state(self, state): TMP1 = "DeparserState nextState = StateDeparseStart;" TMP2 = "return nextState;" stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2)) fname = "compute_next_state" rtype = "DeparserState" params = "DeparserState state" funct = ast.Function(fname, rtype, params, stmt) return funct
def buildTXRX(self): TMP1 = "RX #(BBRequest) rx_%(name)s <- mkRX;" TMP2 = "TX #(BBResponse) tx_%(name)s <- mkTX;" TMP3 = "let rx_info_%(name)s = rx_%(name)s.u;" TMP4 = "let tx_info_%(name)s = tx_%(name)s.u;" stmt = [] pdict = {'name': "prev_control_state"} stmt.append(ast.Template(TMP1, pdict)) stmt.append(ast.Template(TMP2, pdict)) stmt.append(ast.Template(TMP3, pdict)) stmt.append(ast.Template(TMP4, pdict)) return stmt
def build_read_version(self): TMP1 = "let v = `NicVersion;" TMP2 = "indication.read_version_rsp(v);" name = "read_version" rtype = "Action" params = "Bit#(32) version" stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2)) req = ast.Method(name, rtype, stmt=stmt) rsp = ast.Method(name + "_rsp", rtype, params) return req, rsp
def build_bdpi(self, tid, ksz, vsz): global generated_table_sim TMP1 = "`ifndef SVDPI" TMP2 = "import \"BDPI\" function ActionValue#(Bit#(%s)) matchtable_read_%s(Bit#(%s) msgtype);" TMP3 = "import \"BDPI\" function Action matchtable_write_%s(Bit#(%s) msgtype, Bit#(%s) data);" TMP4 = "`endif" stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2 % (vsz, self.name, ksz))) stmt.append(ast.Template(TMP3 % (self.name, ksz, vsz))) stmt.append(ast.Template(TMP4)) return stmt
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 build_read_function(self, tid, ksz, vsz): TMP1 = "let v <- matchtable_read_%s(key);" % (self.name) TMP2 = "return v;" name = "matchtable_read" type = "ActionValue#(Bit#(%s))" % (vsz) params = "Bit#(%s) id, Bit#(%s) key" % (tid, ksz) stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2)) action_block = ast.ActionValueBlock(stmt) funct = ast.Function(name, type, params, stmt=[action_block]) return funct
def build_struct(self): stmt = [] stmt.append(ast.Template('`ifdef DEPARSER_STRUCT\n')) elem = [] elem.append(ast.EnumElement("StateDeparseStart", None, None)) for state in self.deparse_states: elem.append( ast.EnumElement("StateDeparse%s" % (CamelCase(state)), None, None)) state = ast.Enum("DeparserState", elem) stmt.append(state) stmt.append(ast.Template('`endif // DEPARSER_STRUCT\n')) return stmt
def build_types(self): stmt = [] stmt.append(ast.Template("\n")) stmt.append(ast.Template("`ifdef PARSER_STRUCT\n")) elem = [] if self.initial_state == 'default': elem.append(ast.EnumElement("StateDefault", None, None)) for s in self.states.values(): elem.append(ast.EnumElement("State%s" % (CamelCase(s.name)), None, None)) state = ast.Enum("ParserState", elem) stmt.append(state) stmt.append(ast.Template("`endif //PARSER_STRUCT\n")) return stmt
def build_funct_push_phv(self, phv): TMP1 = "MetadataT meta = defaultValue;" TMP2 = "meta.%(field)s = tagged Valid rg_tmp_%(field)s;" TMP3 = "meta_in_ff.enq(meta);" params = "ParserState ty" stmt = [] stmt.append(ast.Template(TMP1)) for _, p in phv: stmt.append(ast.Template(TMP2, {"field": p})) stmt.append(ast.Template(TMP3)) ablock = apply_action_block(stmt) funct = ast.Function("push_phv", 'Action', params, ablock) return funct
def buildTableInstance(self): TMP1 = "%(tblType)s %(tblName)s <- mk%(tblType)s();" TMP2 = "mkConnection(toClient(%(tblName)s_req_ff, %(tblName)s_rsp_ff), %(tblName)s.prev_control_state_%(id)s);" stmt = [] for t in self.tables.values(): stmt.append( ast.Template(TMP1, { "tblType": CamelCase(t.name), "tblName": t.name })) for t in self.tables.values(): stmt.append(ast.Template(TMP2, {"tblName": t.name, "id": 0})) return stmt
def build_transition(name, transition): TMP1 = "w_%(curr_state)s_%(next_state)s.send();" key = transition['value'].replace("0x", "'h") if transition['mask'] is not None: mask = transition['mask'].replace("0x", "'h") else: mask = None next_state = transition['next_state'] next_name = "%s" % (next_state) if next_state != None else self.initial_state stmt = [] stmt.append(ast.Template("dbprint(3, $format(\"transit to %s\"));", next_name)) stmt.append(ast.Template(TMP1 % {'curr_state': name, 'next_state': next_name})) return key, mask, stmt
def buildDefaultRuleStmt(self, tblName): TMP1 = "default_req_ff.deq;" TMP2 = "let _req = default_req_ff.first;" TMP3 = "let meta = _req.meta;" TMP4 = "let pkt = _req.pkt;" TMP5 = "MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};" TMP6 = "%(name)s_req_ff.enq(req);" stmt = [] stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2)) stmt.append(ast.Template(TMP3)) stmt.append(ast.Template(TMP4)) if tblName in self.tables: stmt.append(ast.Template(TMP5)) stmt.append(ast.Template(TMP6, {"name": tblName})) elif tblName in self.conditionals: _stmt = [] self.buildConditionalStmt(tblName, _stmt) stmt += _stmt else: stmt.append( ast.Template( "MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};" )) stmt.append(ast.Template("next_req_ff.enq(req);")) return stmt
def buildCPU (self): tmpl = [] reglist = [] for p in self.primitives: for param in p.parameters: if (param['type'] == 'field'): reglist.append("cons(" + "$".join(param['value'])) #note: use cons to form a list of registers to ALU if len(reglist) != 0: regs = ",".join(reglist) + ", nil" + ")" * len(reglist) tmpl.append(ast.Template("CPU cpu <- mkCPU(%s);" % regs)) tmpl.append(ast.Template("IMem imem <- mkIMem(\"%s.hex\");" % self.name)) tmpl.append(ast.Template("mkConnection(cpu.imem_client, imem.cpu_server);\n")) return tmpl
def build_states(self): stmt = [] stmt.append(ast.Template("\n")) stmt.append(ast.Template("`ifdef PARSER_STATE\n")) for transition in self.state_transitions: stmt.append(ast.Template("PulseWire w_%(name)s <- mkPulseWireOR();\n", {'name': transition})) for _, s in self.states.items(): for op in s.parse_ops: if (op['op'] == 'extract'): for param in op['parameters']: if (param['type'] == 'regular'): htype = GetHeaderType(param['value']) stmt.append(ast.Template("FIFOF#(Maybe#(%(Type)s)) %(type)s_out_ff <- mkDFIFOF(tagged Invalid);\n", {'type': param['value'], 'Type': CamelCase(htype)})) stmt.append(ast.Template("`endif")) return stmt
def buildTXRX(self, pname): TMP1 = "RX #(%(type)sRequest) rx_%(name)s <- mkRX;" TMP3 = "TX #(%(tblname)sResponse) tx_%(name)s <- mkTX;" TMP2 = "let rx_info_%(name)s = rx_%(name)s.u;" TMP4 = "let tx_info_%(name)s = tx_%(name)s.u;" stmt = [] pdict = { 'type': CamelCase(pname), 'name': pname, 'tblname': CamelCase(self.name) } stmt.append(ast.Template(TMP1, pdict)) stmt.append(ast.Template(TMP2, pdict)) stmt.append(ast.Template(TMP3, pdict)) stmt.append(ast.Template(TMP4, pdict)) return stmt
def build_funct_dbg3(): stmt = [] stmt.append(ast.Template("$display(\"(%%0d) \", $time, msg);")) ifstmt = apply_if_verbosity(3, stmt) ablock = apply_action_block(ifstmt) funct = ast.Function("dbg3", 'Action', 'Fmt msg', ablock) return funct
def buildBasicBlocks(self): TMP1 = "%(type)s %(name)s <- mk%(type)s();" stmt = [] stmt.append(ast.Template("// Basic Blocks")) basic_block_set = dict() # to ensure unique name for b in self.basic_blocks: btype = CamelCase(b.name) bname = b.name if bname in basic_block_set: basic_block_set[bname] += 1 name = b.name + "_%s" % (basic_block_set[b.name]) else: basic_block_set[bname] = 0 name = b.name + "_0" stmt.append(ast.Template(TMP1, {"type": btype, "name": name})) return stmt
def buildModuleStmt(self): TMP1 = "Vector#(%(num)s, FIFOF#(BBRequest)) bbReqFifo <- replicateM(mkFIFOF);" TMP2 = "Vector#(%(num)s, FIFOF#(BBResponse)) bbRspFifo <- replicateM(mkFIFOF);" TMP3 = "MatchTable#(%(tid)s, %(sz)s, SizeOf#(%(reqT)s), SizeOf#(%(rspT)s)) matchTable <- mkMatchTable(\"%(name)s\");" TMP4 = "interface next_control_state_%(id)s = toClient(bbReqFifo[%(id)s], bbRspFifo[%(id)s]);" TMP5 = "interface prev_control_state_%(id)s = toServer(rx_%(name)s.e, tx_%(name)s.e);" TMP6 = "Vector#(2, FIFOF#(MetadataT)) metadata_ff <- replicateM(mkFIFOF);" TMP8 = "FIFOF#(MetadataT) metadata_ff <- mkFIFOF;" TMP7 = "FIFOF#(PacketInstance) packet_ff <- mkFIFOF;" stmt = [] stmt += build_funct_verbosity() stmt += self.buildTXRX("metadata") num = len(self.actions) stmt.append(ast.Template(TMP1, {"num": num})) stmt.append(ast.Template(TMP2, {"num": num})) stmt.append(ast.Template(TMP7)) if len(self.key) != 0: reqT = "%sReqT" % (CamelCase(self.name)) rspT = "%sRspT" % (CamelCase(self.name)) # size must be 256 or multiple of 256 size = int(256 * math.ceil(float(self.depth) / 256)) tid = self.tid pdict = { "sz": size, "reqT": reqT, "rspT": rspT, "tid": tid, "name": self.name + '.dat' } stmt.append(ast.Template(TMP3, pdict)) pdict = {"sz": num, "szminus1": num - 1, "fifo": "bbRspFifo"} stmt.append(ast.Template(IRQ_TEMPLATE, pdict)) if len(self.key) != 0: stmt.append(ast.Template(TMP6)) stmt.append(self.buildRuleMatchRequest()) stmt.append(self.buildRuleExecuteAction()) stmt.append(self.buildRuleMatchResponse()) else: stmt.append(ast.Template(TMP8)) stmt.append(self.buildRuleActionRequest()) stmt.append(self.buildRuleActionResponse()) stmt.append(ast.Template(TMP5 % {"name": "metadata", "id": 0})) for idx, _ in enumerate(self.actions): stmt.append(ast.Template(TMP4 % {"id": idx})) stmt += self.build_intf_decl_verbosity() return stmt
def build_rules(self): self.decide_default_state() self.populate_state_transition() stmt = [] stmt.append(ast.Template("\n")) stmt.append(ast.Template("`ifdef PARSER_RULES\n")) stmt += self.build_mutually_exclusive_attribute() stmt += self.build_rule_parse_done() for idx, s in enumerate(self.states.values()): if s.state_type == ParseState.REGULAR: stmt += self.build_rule_state_load(s) stmt += self.build_rule_state_extract(s) stmt += self.build_rule_state_transitions(0, s) else: stmt += self.build_rule_state_transitions(1, s) stmt.append(ast.Template("`endif // PARSER_RULES\n")) return stmt
def buildConditionalStmt(self, tblName, stmt, metadata=set()): TMP1 = "MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};" TMP2 = "%(name)s_req_ff.enq(req);" toCurrPacketFifo = False def search_conditional(name): for key, cond in self.conditionals.items(): print key, cond if key == name: return cond return None if tblName is None: stmt.append( ast.Template( "MetadataRequest req = MetadataRequest {pkt: pkt, meta: meta};" )) stmt.append(ast.Template("next_req_ff.enq(req);")) if tblName in self.tables: stmt.append(ast.Template(TMP1)) stmt.append(ast.Template(TMP2, {"name": tblName})) if tblName in self.conditionals: cond = search_conditional(tblName) expr = cond['expression'].replace("0x", "'h") true_next = cond['true_next'] false_next = cond['false_next'] _meta = cond['metadata'] for m in _meta: if type(m) is list: metadata.add(tuple(m)) else: metadata.add(m) if true_next in self.tables: _stmt = [] _stmt.append(ast.Template(TMP1, {"name": CamelCase(true_next)})) _stmt.append(ast.Template(TMP2, {"name": true_next})) stmt.append(ast.If(expr, _stmt)) if true_next in self.conditionals: _stmt = [] self.buildConditionalStmt(true_next, _stmt, metadata) stmt.append(ast.If(expr, _stmt)) if false_next in self.tables: _stmt = [] _stmt.append( ast.Template(TMP1, {"name": CamelCase(false_next)})) _stmt.append(ast.Template(TMP2, {"name": false_next})) stmt.append(ast.Else(_stmt)) if false_next in self.conditionals: _stmt = [] self.buildConditionalStmt(false_next, _stmt, metadata) stmt.append(ast.Else(_stmt))