Pycode blocks
-------------
-TBD
+Blocks enclosed in ``--pycode-begin--`` and ``--pycode-end--`` lines are interpreted
+as Python code. The function ``output(line)`` can be used to add configuration
+file lines from the python code. The variable ``task`` contains the current task name,
+if any, and ``None`` otherwise. The variable ``tags`` contains a set of all tags
+associated with the current task.
+
+.. code-block:: text
+
+ [tasks]
+ --pycode-begin--
+ for uut in "rotate reflect".split():
+ for op in "SRL SRA SLL SRO SLO ROR ROL FSR FSL".split():
+ output("%s_%s %s %s" % (uut, op, uut, op))
+ --pycode-end--
+
+ ...
+
+ [script]
+ --pycode-begin--
+ for op in "SRL SRA SLL SRO SLO ROR ROL FSR FSL".split():
+ if op in tags:
+ output("read -define %s" % op)
+ --pycode-end--
+ rotate: read -define UUT=shifter_rotate
+ reflect: read -define UUT=shifter_reflect
+ read -sv test.v
+ read -sv shifter_reflect.v
+ read -sv shifter_rotate.v
+ prep -top test
+
+ ...
+
+The command ``sby --dumpcfg <sby_file>`` can be used to print the configuration without
+specialization for any particular task, and ``sby --dumpcfg <sby_file> <task_name>`` can
+be used to print the configuration with specialization for a particular task.
task_skip_block = False
task_skiping_blocks = False
- for line in sbydata:
+ def handle_line(line):
+ nonlocal pycode, tasks_section, task_tags_active, task_tags_all
+ nonlocal task_skip_block, task_skiping_blocks
+
line = line.rstrip("\n")
line = line.rstrip("\r")
+ if pycode is not None:
+ if line == "--pycode-end--":
+ gdict = globals().copy()
+ gdict["task"] = taskname
+ gdict["tags"] = set(task_tags_active)
+ gdict["output_lines"] = list()
+ exec("def output(line):\n output_lines.append(line)\n" + pycode, gdict)
+ pycode = None
+ for line in gdict["output_lines"]:
+ handle_line(line)
+ return
+ pycode += line + "\n"
+ return
+
+ if line == "--pycode-begin--":
+ pycode = ""
+ return
+
if tasks_section and line.startswith("["):
tasks_section = False
if line == "--":
task_skip_block = False
task_skiping_blocks = False
- continue
+ return
found_task_tag = False
task_skip_line = False
sys.exit(1)
if task_skip_line or task_skip_block:
- continue
+ return
if tasks_section:
+ if taskname is None:
+ cfgdata.append(line)
if line.startswith("#"):
- continue
+ return
line = line.split()
if len(line) > 0:
tasklist.append(line[0])
task_tags_all.add(t)
elif line == "[tasks]":
+ if taskname is None:
+ cfgdata.append(line)
tasks_section = True
- elif line == "--pycode-begin--":
- pycode = ""
-
- elif line == "--pycode-end--":
- gdict = globals().copy()
- gdict["cfgdata"] = cfgdata
- gdict["taskname"] = taskname
- exec("def output(line):\n cfgdata.append(line)\n" + pycode, gdict)
- pycode = None
-
else:
- if pycode is None:
- cfgdata.append(line)
- else:
- pycode += line + "\n"
+ cfgdata.append(line)
+
+ for line in sbydata:
+ handle_line(line)
return cfgdata, tasklist