fhdl.xfrm: implement DomainRenamer.
This commit is contained in:
		
							parent
							
								
									8963ab5d9f
								
							
						
					
					
						commit
						9bee90f1bd
					
				|  | @ -573,7 +573,7 @@ class ClockSignal(Value): | |||
|     Parameters | ||||
|     ---------- | ||||
|     domain : str | ||||
|         Clock domain to obtain a clock signal for. Defaults to `"sync"`. | ||||
|         Clock domain to obtain a clock signal for. Defaults to ``"sync"``. | ||||
|     """ | ||||
|     def __init__(self, domain="sync"): | ||||
|         super().__init__() | ||||
|  | @ -588,13 +588,13 @@ class ClockSignal(Value): | |||
| class ResetSignal(Value): | ||||
|     """Reset signal for a given clock domain | ||||
| 
 | ||||
|     `ResetSignal` s for a given clock domain can be retrieved multiple | ||||
|     ``ResetSignal`` s for a given clock domain can be retrieved multiple | ||||
|     times. They all ultimately refer to the same signal. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     domain : str | ||||
|         Clock domain to obtain a reset signal for. Defaults to `"sync"`. | ||||
|         Clock domain to obtain a reset signal for. Defaults to ``"sync"``. | ||||
|     """ | ||||
|     def __init__(self, domain="sync"): | ||||
|         super().__init__() | ||||
|  | @ -603,7 +603,7 @@ class ResetSignal(Value): | |||
|         self.domain = domain | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return "(reset {})".format(self.domain) | ||||
|         return "(rst {})".format(self.domain) | ||||
| 
 | ||||
| 
 | ||||
| class _StatementList(list): | ||||
|  |  | |||
|  | @ -4,7 +4,8 @@ from .ast import * | |||
| from .ir import * | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ["ValueTransformer", "StatementTransformer", "ResetInserter", "CEInserter"] | ||||
| __all__ = ["ValueTransformer", "StatementTransformer", "FragmentTransformer", | ||||
|            "DomainRenamer", "ResetInserter", "CEInserter"] | ||||
| 
 | ||||
| 
 | ||||
| class ValueTransformer: | ||||
|  | @ -116,6 +117,30 @@ class FragmentTransformer: | |||
|         return self.on_fragment(value) | ||||
| 
 | ||||
| 
 | ||||
| class DomainRenamer(FragmentTransformer, ValueTransformer, StatementTransformer): | ||||
|     def __init__(self, domains): | ||||
|         if isinstance(domains, str): | ||||
|             domains = {"sync": domains} | ||||
|         self.domains = OrderedDict(domains) | ||||
| 
 | ||||
|     def on_ClockSignal(self, value): | ||||
|         if value.domain in self.domains: | ||||
|             return ClockSignal(self.domains[value.domain]) | ||||
|         return value | ||||
| 
 | ||||
|     def on_ResetSignal(self, value): | ||||
|         if value.domain in self.domains: | ||||
|             return ResetSignal(self.domains[value.domain]) | ||||
|         return value | ||||
| 
 | ||||
|     def map_drivers(self, fragment, new_fragment): | ||||
|         for cd_name, signals in fragment.iter_domains(): | ||||
|             if cd_name in self.domains: | ||||
|                 cd_name = self.domains[cd_name] | ||||
|             for signal in signals: | ||||
|                 new_fragment.drive(signal, cd_name) | ||||
| 
 | ||||
| 
 | ||||
| class _ControlInserter(FragmentTransformer): | ||||
|     def __init__(self, controls): | ||||
|         if isinstance(controls, Value): | ||||
|  |  | |||
|  | @ -1,12 +1,12 @@ | |||
| import re | ||||
| import unittest | ||||
| from contextlib import contextmanager | ||||
| 
 | ||||
| from nmigen.fhdl.ast import * | ||||
| from nmigen.fhdl.dsl import * | ||||
| from ..fhdl.ast import * | ||||
| from ..fhdl.dsl import * | ||||
| from .tools import * | ||||
| 
 | ||||
| 
 | ||||
| class DSLTestCase(unittest.TestCase): | ||||
| class DSLTestCase(FHDLTestCase): | ||||
|     def setUp(self): | ||||
|         self.s1 = Signal() | ||||
|         self.s2 = Signal() | ||||
|  | @ -24,13 +24,6 @@ class DSLTestCase(unittest.TestCase): | |||
|             # WTF? unittest.assertRaises is completely broken. | ||||
|             self.assertEqual(str(cm.exception), msg) | ||||
| 
 | ||||
|     def assertRepr(self, obj, repr_str): | ||||
|         obj = Statement.wrap(obj) | ||||
|         repr_str = re.sub(r"\s+",   " ",  repr_str) | ||||
|         repr_str = re.sub(r"\( (?=\()", "(", repr_str) | ||||
|         repr_str = re.sub(r"\) (?=\))", ")", repr_str) | ||||
|         self.assertEqual(repr(obj), repr_str.strip()) | ||||
| 
 | ||||
|     def test_d_comb(self): | ||||
|         m = Module() | ||||
|         m.d.comb += self.c1.eq(1) | ||||
|  |  | |||
|  | @ -355,4 +355,4 @@ class ResetSignalTestCase(unittest.TestCase): | |||
| 
 | ||||
|     def test_repr(self): | ||||
|         s1 = ResetSignal() | ||||
|         self.assertEqual(repr(s1), "(reset sync)") | ||||
|         self.assertEqual(repr(s1), "(rst sync)") | ||||
|  | @ -1,25 +1,72 @@ | |||
| import re | ||||
| import unittest | ||||
| 
 | ||||
| from nmigen.fhdl.ast import * | ||||
| from nmigen.fhdl.ir import * | ||||
| from nmigen.fhdl.xfrm import * | ||||
| from ..fhdl.ast import * | ||||
| from ..fhdl.ir import * | ||||
| from ..fhdl.xfrm import * | ||||
| from .tools import * | ||||
| 
 | ||||
| 
 | ||||
| class ResetInserterTestCase(unittest.TestCase): | ||||
| class DomainRenamerTestCase(FHDLTestCase): | ||||
|     def setUp(self): | ||||
|         self.s1 = Signal() | ||||
|         self.s2 = Signal() | ||||
|         self.s3 = Signal() | ||||
|         self.s4 = Signal() | ||||
|         self.s5 = Signal() | ||||
|         self.c1 = Signal() | ||||
| 
 | ||||
|     def test_rename_signals(self): | ||||
|         f = Fragment() | ||||
|         f.add_statements( | ||||
|             self.s1.eq(ClockSignal()), | ||||
|             ResetSignal().eq(self.s2), | ||||
|             self.s3.eq(0), | ||||
|             self.s4.eq(ClockSignal("other")), | ||||
|             self.s5.eq(ResetSignal("other")), | ||||
|         ) | ||||
|         f.drive(self.s1, None) | ||||
|         f.drive(self.s2, None) | ||||
|         f.drive(self.s3, "sync") | ||||
| 
 | ||||
|         f = DomainRenamer("pix")(f) | ||||
|         self.assertRepr(f.statements, """ | ||||
|         ( | ||||
|             (eq (sig s1) (clk pix)) | ||||
|             (eq (rst pix) (sig s2)) | ||||
|             (eq (sig s3) (const 0'd0)) | ||||
|             (eq (sig s4) (clk other)) | ||||
|             (eq (sig s5) (rst other)) | ||||
|         ) | ||||
|         """) | ||||
|         self.assertEqual(f.drivers, { | ||||
|             None: ValueSet((self.s1, self.s2)), | ||||
|             "pix": ValueSet((self.s3,)), | ||||
|         }) | ||||
| 
 | ||||
|     def test_rename_multi(self): | ||||
|         f = Fragment() | ||||
|         f.add_statements( | ||||
|             self.s1.eq(ClockSignal()), | ||||
|             self.s2.eq(ResetSignal("other")), | ||||
|         ) | ||||
| 
 | ||||
|         f = DomainRenamer({"sync": "pix", "other": "pix2"})(f) | ||||
|         self.assertRepr(f.statements, """ | ||||
|         ( | ||||
|             (eq (sig s1) (clk pix)) | ||||
|             (eq (sig s2) (rst pix2)) | ||||
|         ) | ||||
|         """) | ||||
| 
 | ||||
| 
 | ||||
| class ResetInserterTestCase(FHDLTestCase): | ||||
|     def setUp(self): | ||||
|         self.s1 = Signal() | ||||
|         self.s2 = Signal(reset=1) | ||||
|         self.s3 = Signal(reset=1, reset_less=True) | ||||
|         self.c1 = Signal() | ||||
| 
 | ||||
|     def assertRepr(self, obj, repr_str): | ||||
|         obj = Statement.wrap(obj) | ||||
|         repr_str = re.sub(r"\s+",   " ",  repr_str) | ||||
|         repr_str = re.sub(r"\( (?=\()", "(", repr_str) | ||||
|         repr_str = re.sub(r"\) (?=\))", ")", repr_str) | ||||
|         self.assertEqual(repr(obj), repr_str.strip()) | ||||
| 
 | ||||
|     def test_reset_default(self): | ||||
|         f = Fragment() | ||||
|         f.add_statements( | ||||
|  | @ -92,20 +139,13 @@ class ResetInserterTestCase(unittest.TestCase): | |||
|         """) | ||||
| 
 | ||||
| 
 | ||||
| class CEInserterTestCase(unittest.TestCase): | ||||
| class CEInserterTestCase(FHDLTestCase): | ||||
|     def setUp(self): | ||||
|         self.s1 = Signal() | ||||
|         self.s2 = Signal() | ||||
|         self.s3 = Signal() | ||||
|         self.c1 = Signal() | ||||
| 
 | ||||
|     def assertRepr(self, obj, repr_str): | ||||
|         obj = Statement.wrap(obj) | ||||
|         repr_str = re.sub(r"\s+",   " ",  repr_str) | ||||
|         repr_str = re.sub(r"\( (?=\()", "(", repr_str) | ||||
|         repr_str = re.sub(r"\) (?=\))", ")", repr_str) | ||||
|         self.assertEqual(repr(obj), repr_str.strip()) | ||||
| 
 | ||||
|     def test_ce_default(self): | ||||
|         f = Fragment() | ||||
|         f.add_statements( | ||||
|  |  | |||
							
								
								
									
										16
									
								
								nmigen/test/tools.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								nmigen/test/tools.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| import re | ||||
| import unittest | ||||
| 
 | ||||
| from ..fhdl.ast import * | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ["FHDLTestCase"] | ||||
| 
 | ||||
| 
 | ||||
| class FHDLTestCase(unittest.TestCase): | ||||
|     def assertRepr(self, obj, repr_str): | ||||
|         obj = Statement.wrap(obj) | ||||
|         repr_str = re.sub(r"\s+",   " ",  repr_str) | ||||
|         repr_str = re.sub(r"\( (?=\()", "(", repr_str) | ||||
|         repr_str = re.sub(r"\) (?=\))", ")", repr_str) | ||||
|         self.assertEqual(repr(obj), repr_str.strip()) | ||||
		Loading…
	
		Reference in a new issue
	
	 whitequark
						whitequark