`deepcopy` from cache instead of recreating parsers for `GardenSnakeCompiler`
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 5 Oct 2020 22:21:33 +0000 (15:21 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 5 Oct 2020 22:21:33 +0000 (15:21 -0700)
changes `make develop` time from about 1m30s to 1m09s for me

src/soc/decoder/power_decoder.py
src/soc/decoder/power_fields.py
src/soc/decoder/power_fieldsn.py
src/soc/decoder/pseudo/parser.py

index 36b57b07f39a8f0aacd7c7dfdd97411bdb9c49f3..028de9b3b0f78cc488096ff74a2c57a458a75f77 100644 (file)
@@ -451,7 +451,7 @@ class TopPowerDecoder(PowerDecoder):
             setattr(self, fname, sig)
 
         # create signals for all field forms
-        self.form_names = forms = self.fields.instrs.keys()
+        forms = self.form_names
         self.sigforms = {}
         for form in forms:
             fields = self.fields.instrs[form]
@@ -468,6 +468,10 @@ class TopPowerDecoder(PowerDecoder):
 
         self.tree_analyse()
 
+    @property
+    def form_names(self):
+        return self.fields.instrs.keys()
+
     def elaborate(self, platform):
         m = PowerDecoder.elaborate(self, platform)
         comb = m.d.comb
index 02c2dc7025fa425e5a1d0613519dc445f52fe677..58df625b94e4faa5eaafc4eef78ae3a287a09d5c 100644 (file)
@@ -118,9 +118,13 @@ class DecodeFields:
             name_on_wiki = "fields.text"
         self.fname = find_wiki_file(name_on_wiki)
 
+    @property
+    def form_names(self):
+        return self.instrs.keys()
+
     def create_specs(self):
         self.forms, self.instrs = self.decode_fields()
-        self.form_names = forms = self.instrs.keys()
+        forms = self.form_names
         #print ("specs", self.forms, forms)
         for form in forms:
             fields = self.instrs[form]
index eefe929ea41290ea65aef4caaa85524780c41e40..852dd15b079cc88a1b555f71d216107ce2d9c7a1 100644 (file)
@@ -2,6 +2,7 @@ from collections import OrderedDict
 from soc.decoder.power_fields import DecodeFields, BitRange
 from nmigen import Module, Elaboratable, Signal, Cat
 from nmigen.cli import rtlil
+from copy import deepcopy
 
 
 class SignalBitRange(BitRange):
@@ -9,6 +10,15 @@ class SignalBitRange(BitRange):
         BitRange.__init__(self)
         self.signal = signal
 
+    def __deepcopy__(self, memo):
+        signal = deepcopy(self.signal, memo)
+        retval = SignalBitRange(signal=signal)
+        for k, v in self.items():
+            k = deepcopy(k, memo)
+            v = deepcopy(v, memo)
+            retval[k] = v
+        return retval
+
     def _rev(self, k):
         width = self.signal.width
         return width-1-k
index 178caa9ca3494c41d7536969962c640c9c956440..1466f87cf1f63a0526e91910f93534e46716675e 100644 (file)
@@ -11,6 +11,7 @@
 from pprint import pprint
 from ply import lex, yacc
 import astor
+from copy import deepcopy
 
 from soc.decoder.power_decoder import create_pdecode
 from soc.decoder.pseudo.lexer import IndentLexer
@@ -865,10 +866,24 @@ class GardenSnakeParser(PowerParser):
 
 #from compiler import misc, syntax, pycodegen
 
+_CACHED_PARSERS = {}
+_CACHE_PARSERS = True
+
+
 class GardenSnakeCompiler(object):
     def __init__(self, debug=False, form=None, incl_carry=False):
-        self.parser = GardenSnakeParser(debug=debug, form=form,
-                                        incl_carry=incl_carry)
+        if _CACHE_PARSERS:
+            try:
+                parser = _CACHED_PARSERS[debug, form, incl_carry]
+            except KeyError:
+                parser = GardenSnakeParser(debug=debug, form=form,
+                                           incl_carry=incl_carry)
+                _CACHED_PARSERS[debug, form, incl_carry] = parser
+
+            self.parser = deepcopy(parser)
+        else:
+            self.parser = GardenSnakeParser(debug=debug, form=form,
+                                            incl_carry=incl_carry)
 
     def compile(self, code, mode="exec", filename="<string>"):
         tree = self.parser.parse(code)