Improve sby file pycode/tasks handling
authorClifford Wolf <clifford@clifford.at>
Fri, 8 Mar 2019 18:45:32 +0000 (10:45 -0800)
committerClifford Wolf <clifford@clifford.at>
Fri, 8 Mar 2019 18:58:28 +0000 (10:58 -0800)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
docs/source/reference.rst
sbysrc/sby.py

index 26232a962e6e3169897f3c69440ff6520a20d11e..0b6988dfb2608032831c68ee613e2ab4571d8359 100644 (file)
@@ -369,4 +369,38 @@ example:
 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.
index 476992f78a4a7799d5baa08c98d5e69111b8666c..f08f0724f400b8004731f49fa3f01f088a89fa48 100644 (file)
@@ -142,10 +142,31 @@ def read_sbyconfig(sbydata, taskname):
     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
 
@@ -153,7 +174,7 @@ def read_sbyconfig(sbydata, taskname):
             if line == "--":
                 task_skip_block = False
                 task_skiping_blocks = False
-                continue
+                return
 
         found_task_tag = False
         task_skip_line = False
@@ -185,11 +206,13 @@ def read_sbyconfig(sbydata, taskname):
                 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])
@@ -199,23 +222,15 @@ def read_sbyconfig(sbydata, taskname):
                 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