8 pp
= pprint
.PrettyPrinter(indent
=4)
16 opts
, args
= getopt
.getopt(sys
.argv
[1:], "p:o:dg")
29 outfile
= "/dev/stdout"
32 assert a
.endswith(".pmg")
33 if prefix
is None and len(args
) == 1:
35 prefix
= prefix
.split('/')[-1]
38 assert prefix
is not None
40 current_pattern
= None
51 if s
[i
] in ("'", '"') and i
+ 1 < len(s
):
53 while j
+ 1 < len(s
) and s
[j
] != s
[i
]:
54 if s
[j
] == '\\' and j
+ 1 < len(s
):
61 if s
[i
] in ('$', '\\') and i
+ 1 < len(s
):
67 if ord('a') <= ord(s
[j
]) <= ord('z'):
70 if ord('A') <= ord(s
[j
]) <= ord('Z'):
73 if ord('0') <= ord(s
[j
]) <= ord('9'):
107 def process_pmgfile(f
):
108 global current_pattern
115 if len(cmd
) == 0 or cmd
[0].startswith("//"): continue
119 if current_pattern
is not None:
121 block
["type"] = "final"
122 block
["pattern"] = current_pattern
125 assert len(line
) == 2
126 assert line
[1] not in patterns
127 current_pattern
= line
[1]
128 patterns
[current_pattern
] = len(blocks
)
129 state_types
[current_pattern
] = dict()
130 udata_types
[current_pattern
] = dict()
133 assert current_pattern
is not None
136 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
)
138 type_str
= m
.group(1)
139 states_str
= m
.group(2)
140 for s
in re
.split(r
"\s+", states_str
):
141 assert s
not in state_types
[current_pattern
]
142 state_types
[current_pattern
][s
] = type_str
146 m
= re
.match(r
"^udata\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line
)
148 type_str
= m
.group(1)
149 udatas_str
= m
.group(2)
150 for s
in re
.split(r
"\s+", udatas_str
):
151 assert s
not in udata_types
[current_pattern
]
152 udata_types
[current_pattern
][s
] = type_str
157 block
["type"] = "match"
158 block
["pattern"] = current_pattern
161 assert len(line
) == 2
162 assert line
[1] not in state_types
[current_pattern
]
163 block
["cell"] = line
[1]
164 state_types
[current_pattern
][line
[1]] = "Cell*";
167 block
["select"] = list()
168 block
["index"] = list()
169 block
["filter"] = list()
170 block
["optional"] = False
176 if len(a
) == 0 or a
[0].startswith("//"): continue
177 if a
[0] == "endmatch": break
181 block
["if"].append(rewrite_cpp(b
.strip()))
186 block
["select"].append(rewrite_cpp(b
.strip()))
190 m
= re
.match(r
"^\s*index\s+<(.*?)>\s+(.*?)\s*===\s*(.*?)\s*$", l
)
192 block
["index"].append((m
.group(1), rewrite_cpp(m
.group(2)), rewrite_cpp(m
.group(3))))
197 block
["filter"].append(rewrite_cpp(b
.strip()))
200 if a
[0] == "optional":
201 block
["optional"] = True
211 block
["type"] = "code"
212 block
["pattern"] = current_pattern
214 block
["code"] = list()
215 block
["states"] = set()
217 for s
in line
.split()[1:]:
218 assert s
in state_types
[current_pattern
]
219 block
["states"].add(s
)
225 if len(a
) == 0: continue
226 if a
[0] == "endcode": break
228 block
["code"].append(rewrite_cpp(l
.rstrip()))
236 with
open(fn
, "r") as f
:
239 if current_pattern
is not None:
241 block
["type"] = "final"
242 block
["pattern"] = current_pattern
245 current_pattern
= None
250 with
open(outfile
, "w") as f
:
252 print("// Generated by pmgen.py from {}".format(fn
), file=f
)
256 print("#include \"kernel/yosys.h\"", file=f
)
257 print("#include \"kernel/sigtools.h\"", file=f
)
259 print("YOSYS_NAMESPACE_BEGIN", file=f
)
262 print("struct {}_pm {{".format(prefix
), file=f
)
263 print(" Module *module;", file=f
)
264 print(" SigMap sigmap;", file=f
)
265 print(" std::function<void()> on_accept;".format(prefix
), file=f
)
268 for index
in range(len(blocks
)):
269 block
= blocks
[index
]
270 if block
["type"] == "match":
272 for entry
in block
["index"]:
273 index_types
.append(entry
[0])
274 print(" typedef std::tuple<{}> index_{}_key_type;".format(", ".join(index_types
), index
), file=f
)
275 print(" dict<index_{}_key_type, vector<Cell*>> index_{};".format(index
, index
), file=f
)
276 print(" dict<SigBit, pool<Cell*>> sigusers;", file=f
)
277 print(" pool<Cell*> blacklist_cells;", file=f
)
278 print(" pool<Cell*> autoremove_cells;", file=f
)
279 print(" bool blacklist_dirty;", file=f
)
280 print(" int rollback;", file=f
)
283 for current_pattern
in sorted(patterns
.keys()):
284 print(" struct state_{}_t {{".format(current_pattern
), file=f
)
285 for s
, t
in sorted(state_types
[current_pattern
].items()):
286 print(" {} {};".format(t
, s
), file=f
)
287 print(" }} st_{};".format(current_pattern
), file=f
)
290 print(" struct udata_{}_t {{".format(current_pattern
), file=f
)
291 for s
, t
in sorted(udata_types
[current_pattern
].items()):
292 print(" {} {};".format(t
, s
), file=f
)
293 print(" }} ud_{};".format(current_pattern
), file=f
)
295 current_pattern
= None
297 for v
, n
in sorted(ids
.items()):
299 print(" IdString {}{{\"\\{}\"}};".format(v
, n
), file=f
)
301 print(" IdString {}{{\"{}\"}};".format(v
, n
), file=f
)
304 print(" void add_siguser(const SigSpec &sig, Cell *cell) {", file=f
)
305 print(" for (auto bit : sigmap(sig)) {", file=f
)
306 print(" if (bit.wire == nullptr) continue;", file=f
)
307 print(" if (sigusers.count(bit) == 0 && bit.wire->port_id)", file=f
)
308 print(" sigusers[bit].insert(nullptr);", file=f
)
309 print(" sigusers[bit].insert(cell);", file=f
)
314 print(" void blacklist(Cell *cell) {", file=f
)
315 print(" if (cell != nullptr) {", file=f
)
316 print(" if (blacklist_cells.insert(cell).second)", file=f
)
317 print(" blacklist_dirty = true;", file=f
)
322 print(" void autoremove(Cell *cell) {", file=f
)
323 print(" if (cell != nullptr) {", file=f
)
324 print(" if (blacklist_cells.insert(cell).second)", file=f
)
325 print(" blacklist_dirty = true;", file=f
)
326 print(" autoremove_cells.insert(cell);", file=f
)
331 for current_pattern
in sorted(patterns
.keys()):
332 print(" void check_blacklist_{}() {{".format(current_pattern
), file=f
)
333 print(" if (!blacklist_dirty)", file=f
)
334 print(" return;", file=f
)
335 print(" blacklist_dirty = false;", file=f
)
336 for index
in range(len(blocks
)):
337 block
= blocks
[index
]
338 if block
["pattern"] != current_pattern
:
340 if block
["type"] == "match":
341 print(" if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern
, block
["cell"], current_pattern
, block
["cell"]), file=f
)
342 print(" rollback = {};".format(index
+1), file=f
)
343 print(" return;", file=f
)
345 print(" rollback = 0;", file=f
)
348 current_pattern
= None
350 print(" SigSpec port(Cell *cell, IdString portname) {", file=f
)
351 print(" return sigmap(cell->getPort(portname));", file=f
)
355 print(" Const param(Cell *cell, IdString paramname) {", file=f
)
356 print(" return cell->getParam(paramname);", file=f
)
360 print(" int nusers(const SigSpec &sig) {", file=f
)
361 print(" pool<Cell*> users;", file=f
)
362 print(" for (auto bit : sigmap(sig))", file=f
)
363 print(" for (auto user : sigusers[bit])", file=f
)
364 print(" users.insert(user);", file=f
)
365 print(" return GetSize(users);", file=f
)
369 print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix
), file=f
)
370 print(" module(module), sigmap(module) {", file=f
)
371 for current_pattern
in sorted(patterns
.keys()):
372 for s
, t
in sorted(udata_types
[current_pattern
].items()):
374 print(" ud_{}.{} = nullptr;".format(current_pattern
,s
), file=f
)
376 print(" ud_{}.{} = {}();".format(current_pattern
, s
, t
), file=f
)
377 current_pattern
= None
378 print(" for (auto cell : module->cells()) {", file=f
)
379 print(" for (auto &conn : cell->connections())", file=f
)
380 print(" add_siguser(conn.second, cell);", file=f
)
382 print(" for (auto cell : cells) {", file=f
)
384 for index
in range(len(blocks
)):
385 block
= blocks
[index
]
386 if block
["type"] == "match":
387 print(" do {", file=f
)
388 print(" Cell *{} = cell;".format(block
["cell"]), file=f
)
389 for expr
in block
["select"]:
390 print(" if (!({})) break;".format(expr
), file=f
)
391 print(" index_{}_key_type key;".format(index
), file=f
)
392 for field
, entry
in enumerate(block
["index"]):
393 print(" std::get<{}>(key) = {};".format(field
, entry
[1]), file=f
)
394 print(" index_{}[key].push_back(cell);".format(index
), file=f
)
395 print(" } while (0);", file=f
)
401 print(" ~{}_pm() {{".format(prefix
), file=f
)
402 print(" for (auto cell : autoremove_cells)", file=f
)
403 print(" module->remove(cell);", file=f
)
407 for current_pattern
in sorted(patterns
.keys()):
408 print(" void run_{}(std::function<void()> on_accept_f) {{".format(current_pattern
), file=f
)
409 print(" on_accept = on_accept_f;", file=f
)
410 print(" rollback = 0;", file=f
)
411 print(" blacklist_dirty = false;", file=f
)
412 for s
, t
in sorted(state_types
[current_pattern
].items()):
414 print(" st_{}.{} = nullptr;".format(current_pattern
, s
), file=f
)
416 print(" st_{}.{} = {}();".format(current_pattern
, s
, t
), file=f
)
417 print(" block_{}();".format(patterns
[current_pattern
]), file=f
)
420 print(" void run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern
, prefix
), file=f
)
421 print(" run_{}([&](){{on_accept_f(*this);}});".format(current_pattern
), file=f
)
424 print(" void run_{}(std::function<void(state_{}_t&)> on_accept_f) {{".format(current_pattern
, current_pattern
), file=f
)
425 print(" run_{}([&](){{on_accept_f(st_{});}});".format(current_pattern
, current_pattern
), file=f
)
428 print(" void run_{}() {{".format(current_pattern
), file=f
)
429 print(" run_{}([](){{}});".format(current_pattern
, current_pattern
), file=f
)
432 current_pattern
= None
434 for index
in range(len(blocks
)):
435 block
= blocks
[index
]
437 print(" void block_{}() {{".format(index
), file=f
)
438 current_pattern
= block
["pattern"]
440 if block
["type"] == "final":
441 print(" on_accept();", file=f
)
442 print(" check_blacklist_{}();".format(current_pattern
), file=f
)
444 if index
+1 != len(blocks
):
452 for i
in range(patterns
[current_pattern
], index
):
453 if blocks
[i
]["type"] == "code":
454 for s
in blocks
[i
]["states"]:
456 elif blocks
[i
]["type"] == "match":
457 const_st
.add(blocks
[i
]["cell"])
461 if block
["type"] == "code":
462 for s
in block
["states"]:
467 elif block
["type"] == "match":
469 assert s
not in const_st
474 for s
in sorted(const_st
):
475 t
= state_types
[current_pattern
][s
]
477 print(" {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t
, s
, current_pattern
, s
), file=f
)
479 print(" const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t
, s
, current_pattern
, s
), file=f
)
481 for s
in sorted(nonconst_st
):
482 t
= state_types
[current_pattern
][s
]
483 print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t
, s
, current_pattern
, s
), file=f
)
487 for s
in sorted(restore_st
):
488 t
= state_types
[current_pattern
][s
]
489 print(" {} backup_{} = {};".format(t
, s
, s
), file=f
)
491 if block
["type"] == "code":
493 print(" do {", file=f
)
494 print("#define reject do {{ check_blacklist_{}(); goto rollback_label; }} while(0)".format(current_pattern
), file=f
)
495 print("#define accept do {{ on_accept(); check_blacklist_{}(); if (rollback) goto rollback_label; }} while(0)".format(current_pattern
), file=f
)
496 print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index
+1), file=f
)
498 for line
in block
["code"]:
499 print(" " + line
, file=f
)
502 print(" block_{}();".format(index
+1), file=f
)
503 print("#undef reject", file=f
)
504 print("#undef accept", file=f
)
505 print("#undef branch", file=f
)
506 print(" } while (0);", file=f
)
508 print("rollback_label:", file=f
)
509 print(" YS_ATTRIBUTE(unused);", file=f
)
511 if len(restore_st
) or len(nonconst_st
):
513 for s
in sorted(restore_st
):
514 t
= state_types
[current_pattern
][s
]
515 print(" {} = backup_{};".format(s
, s
), file=f
)
516 for s
in sorted(nonconst_st
):
517 if s
not in restore_st
:
518 t
= state_types
[current_pattern
][s
]
520 print(" {} = nullptr;".format(s
), file=f
)
522 print(" {} = {}();".format(s
, t
), file=f
)
524 elif block
["type"] == "match":
525 assert len(restore_st
) == 0
528 for expr
in block
["if"]:
530 print(" if (!({})) {{".format(expr
), file=f
)
531 print(" {} = nullptr;".format(block
["cell"]), file=f
)
532 print(" block_{}();".format(index
+1), file=f
)
533 print(" return;", file=f
)
537 print(" index_{}_key_type key;".format(index
), file=f
)
538 for field
, entry
in enumerate(block
["index"]):
539 print(" std::get<{}>(key) = {};".format(field
, entry
[2]), file=f
)
540 print(" const vector<Cell*> &cells = index_{}[key];".format(index
), file=f
)
543 print(" for (int idx = 0; idx < GetSize(cells); idx++) {", file=f
)
544 print(" {} = cells[idx];".format(block
["cell"]), file=f
)
545 print(" if (blacklist_cells.count({})) continue;".format(block
["cell"]), file=f
)
546 for expr
in block
["filter"]:
547 print(" if (!({})) continue;".format(expr
), file=f
)
548 print(" block_{}();".format(index
+1), file=f
)
549 print(" if (rollback) {", file=f
)
550 print(" if (rollback != {}) {{".format(index
+1), file=f
)
551 print(" {} = nullptr;".format(block
["cell"]), file=f
)
552 print(" return;", file=f
)
554 print(" rollback = 0;", file=f
)
559 print(" {} = nullptr;".format(block
["cell"]), file=f
)
561 if block
["optional"]:
562 print(" block_{}();".format(index
+1), file=f
)
567 current_pattern
= None
575 print("YOSYS_NAMESPACE_END", file=f
)