diff options
| author | Clifford Wolf <clifford@clifford.at> | 2019-04-29 13:02:05 +0200 | 
|---|---|---|
| committer | Clifford Wolf <clifford@clifford.at> | 2019-04-29 13:02:05 +0200 | 
| commit | 9f792c599db0cc466444d58e3c675711deb6349b (patch) | |
| tree | 483be9da99afb9b62e98bccc672f02a63f6dac9a /passes/pmgen/pmgen.py | |
| parent | 32881a989c2eb2cc73e224e6dc20dc3949f90e55 (diff) | |
| download | yosys-9f792c599db0cc466444d58e3c675711deb6349b.tar.gz yosys-9f792c599db0cc466444d58e3c675711deb6349b.tar.bz2 yosys-9f792c599db0cc466444d58e3c675711deb6349b.zip | |
Add pmgen support for multiple patterns in one matcher
Signed-off-by: Clifford Wolf <clifford@clifford.at>
Diffstat (limited to 'passes/pmgen/pmgen.py')
| -rw-r--r-- | passes/pmgen/pmgen.py | 202 | 
1 files changed, 128 insertions, 74 deletions
| diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index edc1ad7fe..bb4c9d66b 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -10,14 +10,17 @@ pp = pprint.PrettyPrinter(indent=4)  prefix = None  pmgfiles = list()  outfile = None +debug = False -opts, args = getopt.getopt(sys.argv[1:], "p:o:") +opts, args = getopt.getopt(sys.argv[1:], "p:o:d")  for o, a in opts:      if o == "-p": -        prefix = o +        prefix = a      elif o == "-o":          outfile = a +    elif o == "-d": +        debug = True  if outfile is None:      outfile = args[-1] @@ -32,6 +35,8 @@ for a in args:  assert prefix is not None +current_pattern = None +patterns = dict()  state_types = dict()  udata_types = dict()  blocks = list() @@ -98,6 +103,7 @@ def rewrite_cpp(s):      return "".join(t)  def process_pmgfile(f): +    global current_pattern      while True:          line = f.readline()          if line == "": break @@ -107,14 +113,31 @@ def process_pmgfile(f):          if len(cmd) == 0 or cmd[0].startswith("//"): continue          cmd = cmd[0] +        if cmd == "pattern": +            if current_pattern is not None: +                block = dict() +                block["type"] = "final" +                block["pattern"] = current_pattern +                blocks.append(block) +            line = line.split() +            assert len(line) == 2 +            assert line[1] not in patterns +            current_pattern = line[1] +            patterns[current_pattern] = len(blocks) +            state_types[current_pattern] = dict() +            udata_types[current_pattern] = dict() +            continue + +        assert current_pattern is not None +          if cmd == "state":              m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line)              assert m              type_str = m.group(1)              states_str = m.group(2)              for s in re.split(r"\s+", states_str): -                assert s not in state_types -                state_types[s] = type_str +                assert s not in state_types[current_pattern] +                state_types[current_pattern][s] = type_str              continue          if cmd == "udata": @@ -123,19 +146,20 @@ def process_pmgfile(f):              type_str = m.group(1)              udatas_str = m.group(2)              for s in re.split(r"\s+", udatas_str): -                assert s not in udata_types -                udata_types[s] = type_str +                assert s not in udata_types[current_pattern] +                udata_types[current_pattern][s] = type_str              continue          if cmd == "match":              block = dict()              block["type"] = "match" +            block["pattern"] = current_pattern              line = line.split()              assert len(line) == 2 -            assert line[1] not in state_types +            assert line[1] not in state_types[current_pattern]              block["cell"] = line[1] -            state_types[line[1]] = "Cell*"; +            state_types[current_pattern][line[1]] = "Cell*";              block["if"] = list()              block["select"] = list() @@ -178,15 +202,18 @@ def process_pmgfile(f):                  assert False              blocks.append(block) +            continue          if cmd == "code":              block = dict()              block["type"] = "code" +            block["pattern"] = current_pattern +              block["code"] = list()              block["states"] = set()              for s in line.split()[1:]: -                assert s in state_types +                assert s in state_types[current_pattern]                  block["states"].add(s)              while True: @@ -199,11 +226,25 @@ def process_pmgfile(f):                  block["code"].append(rewrite_cpp(l.rstrip()))              blocks.append(block) +            continue + +        assert False  for fn in pmgfiles:      with open(fn, "r") as f:          process_pmgfile(f) +if current_pattern is not None: +    block = dict() +    block["type"] = "final" +    block["pattern"] = current_pattern +    blocks.append(block) + +current_pattern = None + +if debug: +    pp.pprint(blocks) +  with open(outfile, "w") as f:      print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f)      print("", file=f) @@ -236,17 +277,19 @@ with open(outfile, "w") as f:      print("  int rollback;", file=f)      print("", file=f) -    print("  struct state_t {", file=f) -    for s, t in sorted(state_types.items()): -        print("    {} {};".format(t, s), file=f) -    print("  } st;", file=f) -    print("", file=f) +    for current_pattern in sorted(patterns.keys()): +        print("  struct state_{}_t {{".format(current_pattern), file=f) +        for s, t in sorted(state_types[current_pattern].items()): +            print("    {} {};".format(t, s), file=f) +        print("  }} st_{};".format(current_pattern), file=f) +        print("", file=f) -    print("  struct udata_t {", file=f) -    for s, t in sorted(udata_types.items()): -        print("    {} {};".format(t, s), file=f) -    print("  } ud;", file=f) -    print("", file=f) +        print("  struct udata_{}_t {{".format(current_pattern), file=f) +        for s, t in sorted(udata_types[current_pattern].items()): +            print("    {} {};".format(t, s), file=f) +        print("  }} ud_{};".format(current_pattern), file=f) +        print("", file=f) +    current_pattern = None      for v, n in sorted(ids.items()):          if n[0] == "\\": @@ -282,20 +325,22 @@ with open(outfile, "w") as f:      print("  }", file=f)      print("", file=f) -    print("  void check_blacklist() {", file=f) -    print("    if (!blacklist_dirty)", file=f) -    print("      return;", file=f) -    print("    blacklist_dirty = false;", file=f) -    for index in range(len(blocks)): -        block = blocks[index] -        if block["type"] == "match": -            print("    if (st.{} != nullptr && blacklist_cells.count(st.{})) {{".format(block["cell"], block["cell"]), file=f) -            print("      rollback = {};".format(index+1), file=f) -            print("      return;", file=f) -            print("    }", file=f) -    print("    rollback = 0;", file=f) -    print("  }", file=f) -    print("", file=f) +    for current_pattern in sorted(patterns.keys()): +        print("  void check_blacklist_{}() {{".format(current_pattern), file=f) +        print("    if (!blacklist_dirty)", file=f) +        print("      return;", file=f) +        print("    blacklist_dirty = false;", file=f) +        for index in range(len(blocks)): +            block = blocks[index] +            if block["type"] == "match": +                print("    if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f) +                print("      rollback = {};".format(index+1), file=f) +                print("      return;", file=f) +                print("    }", file=f) +        print("    rollback = 0;", file=f) +        print("  }", file=f) +        print("", file=f) +    current_pattern = None      print("  SigSpec port(Cell *cell, IdString portname) {", file=f)      print("    return sigmap(cell->getPort(portname));", file=f) @@ -318,11 +363,13 @@ with open(outfile, "w") as f:      print("  {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f)      print("      module(module), sigmap(module) {", file=f) -    for s, t in sorted(udata_types.items()): -        if t.endswith("*"): -            print("    ud.{} = nullptr;".format(s), file=f) -        else: -            print("    ud.{} = {}();".format(s, t), file=f) +    for current_pattern in sorted(patterns.keys()): +        for s, t in sorted(udata_types[current_pattern].items()): +            if t.endswith("*"): +                print("    ud_{}.{} = nullptr;".format(current_pattern,s), file=f) +            else: +                print("    ud_{}.{} = {}();".format(current_pattern, s, t), file=f) +    current_pattern = None      print("    for (auto cell : module->cells()) {", file=f)      print("      for (auto &conn : cell->connections())", file=f)      print("        add_siguser(conn.second, cell);", file=f) @@ -352,34 +399,48 @@ with open(outfile, "w") as f:      print("  }", file=f)      print("", file=f) -    print("  void run(std::function<void()> on_accept_f) {", file=f) -    print("    on_accept = on_accept_f;", file=f) -    print("    rollback = 0;", file=f) -    print("    blacklist_dirty = false;", file=f) -    for s, t in sorted(state_types.items()): -        if t.endswith("*"): -            print("    st.{} = nullptr;".format(s), file=f) -        else: -            print("    st.{} = {}();".format(s, t), file=f) -    print("    block_0();", file=f) -    print("  }", file=f) -    print("", file=f) - -    print("  void run(std::function<void({}_pm&)> on_accept_f) {{".format(prefix), file=f) -    print("    run([&](){on_accept_f(*this);});", file=f) -    print("  }", file=f) -    print("", file=f) +    for current_pattern in sorted(patterns.keys()): +        print("  void run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f) +        print("    on_accept = on_accept_f;", file=f) +        print("    rollback = 0;", file=f) +        print("    blacklist_dirty = false;", file=f) +        for s, t in sorted(state_types[current_pattern].items()): +            if t.endswith("*"): +                print("    st_{}.{} = nullptr;".format(current_pattern, s), file=f) +            else: +                print("    st_{}.{} = {}();".format(current_pattern, s, t), file=f) +        print("    block_{}();".format(patterns[current_pattern]), file=f) +        print("  }", file=f) +        print("", file=f) +        print("  void run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern, prefix), file=f) +        print("    run_{}([&](){{on_accept_f(*this);}});".format(current_pattern), file=f) +        print("  }", file=f) +        print("", file=f) +        print("  void run_{}(std::function<void(state_{}_t&)> on_accept_f) {{".format(current_pattern, current_pattern), file=f) +        print("    run_{}([&](){{on_accept_f(st_{});}});".format(current_pattern, current_pattern), file=f) +        print("  }", file=f) +        print("", file=f) +    current_pattern = None      for index in range(len(blocks)):          block = blocks[index]          print("  void block_{}() {{".format(index), file=f) +        current_pattern = block["pattern"] + +        if block["type"] == "final": +            print("    on_accept();", file=f) +            print("    check_blacklist_{}();".format(current_pattern), file=f) +            print("  }", file=f) +            if index+1 != len(blocks): +                print("", file=f) +            continue          const_st = set()          nonconst_st = set()          restore_st = set() -        for i in range(index): +        for i in range(patterns[current_pattern], index):              if blocks[i]["type"] == "code":                  for s in blocks[i]["states"]:                      const_st.add(s) @@ -402,27 +463,27 @@ with open(outfile, "w") as f:              assert False          for s in sorted(const_st): -            t = state_types[s] +            t = state_types[current_pattern][s]              if t.endswith("*"): -                print("    {} const &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) +                print("    {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)              else: -                print("    const {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) +                print("    const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)          for s in sorted(nonconst_st): -            t = state_types[s] -            print("    {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) +            t = state_types[current_pattern][s] +            print("    {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f)          if len(restore_st):              print("", file=f)              for s in sorted(restore_st): -                t = state_types[s] +                t = state_types[current_pattern][s]                  print("    {} backup_{} = {};".format(t, s, s), file=f)          if block["type"] == "code":              print("", file=f)              print("    do {", file=f) -            print("#define reject do { check_blacklist(); goto rollback_label; } while(0)", file=f) -            print("#define accept do { on_accept(); check_blacklist(); if (rollback) goto rollback_label; } while(0)", file=f) +            print("#define reject do {{ check_blacklist_{}(); goto rollback_label; }} while(0)".format(current_pattern), file=f) +            print("#define accept do {{ on_accept(); check_blacklist_{}(); if (rollback) goto rollback_label; }} while(0)".format(current_pattern), file=f)              print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f)              for line in block["code"]: @@ -441,11 +502,11 @@ with open(outfile, "w") as f:              if len(restore_st) or len(nonconst_st):                  print("", file=f)                  for s in sorted(restore_st): -                    t = state_types[s] +                    t = state_types[current_pattern][s]                      print("    {} = backup_{};".format(s, s), file=f)                  for s in sorted(nonconst_st):                      if s not in restore_st: -                        t = state_types[s] +                        t = state_types[current_pattern][s]                          if t.endswith("*"):                              print("    {} = nullptr;".format(s), file=f)                          else: @@ -494,17 +555,10 @@ with open(outfile, "w") as f:          else:              assert False - +        current_pattern = None          print("  }", file=f)          print("", file=f) -    print("  void block_{}() {{".format(len(blocks)), file=f) -    print("    on_accept();", file=f) -    print("    check_blacklist();", file=f) -    print("  }", file=f)      print("};", file=f) -      print("", file=f)      print("YOSYS_NAMESPACE_END", file=f) - -# pp.pprint(blocks) | 
