compat: import genlib.record from Migen.
This commit is contained in:
		
							parent
							
								
									a90748303c
								
							
						
					
					
						commit
						0f2c7e7161
					
				|  | @ -7,5 +7,5 @@ from .fhdl.bitcontainer import * | |||
| 
 | ||||
| from .sim import * | ||||
| 
 | ||||
| # from .genlib.record import * | ||||
| from .genlib.record import * | ||||
| from .genlib.fsm import * | ||||
|  |  | |||
							
								
								
									
										195
									
								
								nmigen/compat/genlib/record.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								nmigen/compat/genlib/record.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,195 @@ | |||
| from ...tracer import * | ||||
| from ..fhdl.structure import * | ||||
| 
 | ||||
| from functools import reduce | ||||
| from operator import or_ | ||||
| 
 | ||||
| 
 | ||||
| (DIR_NONE, DIR_S_TO_M, DIR_M_TO_S) = range(3) | ||||
| 
 | ||||
| # Possible layout elements: | ||||
| #   1. (name, size) | ||||
| #   2. (name, size, direction) | ||||
| #   3. (name, sublayout) | ||||
| # size can be an int, or a (int, bool) tuple for signed numbers | ||||
| # sublayout must be a list | ||||
| 
 | ||||
| 
 | ||||
| def set_layout_parameters(layout, **layout_dict): | ||||
|     def resolve(p): | ||||
|         if isinstance(p, str): | ||||
|             try: | ||||
|                 return layout_dict[p] | ||||
|             except KeyError: | ||||
|                 return p | ||||
|         else: | ||||
|             return p | ||||
| 
 | ||||
|     r = [] | ||||
|     for f in layout: | ||||
|         if isinstance(f[1], (int, tuple, str)):  # cases 1/2 | ||||
|             if len(f) == 3: | ||||
|                 r.append((f[0], resolve(f[1]), f[2])) | ||||
|             else: | ||||
|                 r.append((f[0], resolve(f[1]))) | ||||
|         elif isinstance(f[1], list):  # case 3 | ||||
|             r.append((f[0], set_layout_parameters(f[1], **layout_dict))) | ||||
|         else: | ||||
|             raise TypeError | ||||
|     return r | ||||
| 
 | ||||
| 
 | ||||
| def layout_len(layout): | ||||
|     r = 0 | ||||
|     for f in layout: | ||||
|         if isinstance(f[1], (int, tuple)):  # cases 1/2 | ||||
|             if len(f) == 3: | ||||
|                 fname, fsize, fdirection = f | ||||
|             else: | ||||
|                 fname, fsize = f | ||||
|         elif isinstance(f[1], list):  # case 3 | ||||
|             fname, fsublayout = f | ||||
|             fsize = layout_len(fsublayout) | ||||
|         else: | ||||
|             raise TypeError | ||||
|         if isinstance(fsize, tuple): | ||||
|             r += fsize[0] | ||||
|         else: | ||||
|             r += fsize | ||||
|     return r | ||||
| 
 | ||||
| 
 | ||||
| def layout_get(layout, name): | ||||
|     for f in layout: | ||||
|         if f[0] == name: | ||||
|             return f | ||||
|     raise KeyError(name) | ||||
| 
 | ||||
| 
 | ||||
| def layout_partial(layout, *elements): | ||||
|     r = [] | ||||
|     for path in elements: | ||||
|         path_s = path.split("/") | ||||
|         last = path_s.pop() | ||||
|         copy_ref = layout | ||||
|         insert_ref = r | ||||
|         for hop in path_s: | ||||
|             name, copy_ref = layout_get(copy_ref, hop) | ||||
|             try: | ||||
|                 name, insert_ref = layout_get(insert_ref, hop) | ||||
|             except KeyError: | ||||
|                 new_insert_ref = [] | ||||
|                 insert_ref.append((hop, new_insert_ref)) | ||||
|                 insert_ref = new_insert_ref | ||||
|         insert_ref.append(layout_get(copy_ref, last)) | ||||
|     return r | ||||
| 
 | ||||
| 
 | ||||
| class Record: | ||||
|     def __init__(self, layout, name=None, **kwargs): | ||||
|         try: | ||||
|             self.name = get_var_name() | ||||
|         except NameNotFound: | ||||
|             self.name = "" | ||||
|         self.layout = layout | ||||
| 
 | ||||
|         if self.name: | ||||
|             prefix = self.name + "_" | ||||
|         else: | ||||
|             prefix = "" | ||||
|         for f in self.layout: | ||||
|             if isinstance(f[1], (int, tuple)):  # cases 1/2 | ||||
|                 if(len(f) == 3): | ||||
|                     fname, fsize, fdirection = f | ||||
|                 else: | ||||
|                     fname, fsize = f | ||||
|                 finst = Signal(fsize, name=prefix + fname, **kwargs) | ||||
|             elif isinstance(f[1], list):  # case 3 | ||||
|                 fname, fsublayout = f | ||||
|                 finst = Record(fsublayout, prefix + fname, **kwargs) | ||||
|             else: | ||||
|                 raise TypeError | ||||
|             setattr(self, fname, finst) | ||||
| 
 | ||||
|     def eq(self, other): | ||||
|         return [getattr(self, f[0]).eq(getattr(other, f[0])) | ||||
|           for f in self.layout if hasattr(other, f[0])] | ||||
| 
 | ||||
|     def iter_flat(self): | ||||
|         for f in self.layout: | ||||
|             e = getattr(self, f[0]) | ||||
|             if isinstance(e, Signal): | ||||
|                 if len(f) == 3: | ||||
|                     yield e, f[2] | ||||
|                 else: | ||||
|                     yield e, DIR_NONE | ||||
|             elif isinstance(e, Record): | ||||
|                 yield from e.iter_flat() | ||||
|             else: | ||||
|                 raise TypeError | ||||
| 
 | ||||
|     def flatten(self): | ||||
|         return [signal for signal, direction in self.iter_flat()] | ||||
| 
 | ||||
|     def raw_bits(self): | ||||
|         return Cat(*self.flatten()) | ||||
| 
 | ||||
|     def connect(self, *slaves, keep=None, omit=None): | ||||
|         if keep is None: | ||||
|             _keep = set([f[0] for f in self.layout]) | ||||
|         elif isinstance(keep, list): | ||||
|             _keep = set(keep) | ||||
|         else: | ||||
|             _keep = keep | ||||
|         if omit is None: | ||||
|             _omit = set() | ||||
|         elif isinstance(omit, list): | ||||
|             _omit = set(omit) | ||||
|         else: | ||||
|             _omit = omit | ||||
| 
 | ||||
|         _keep = _keep - _omit | ||||
| 
 | ||||
|         r = [] | ||||
|         for f in self.layout: | ||||
|             field = f[0] | ||||
|             self_e = getattr(self, field) | ||||
|             if isinstance(self_e, Signal): | ||||
|                 if field in _keep: | ||||
|                     direction = f[2] | ||||
|                     if direction == DIR_M_TO_S: | ||||
|                         r += [getattr(slave, field).eq(self_e) for slave in slaves] | ||||
|                     elif direction == DIR_S_TO_M: | ||||
|                         r.append(self_e.eq(reduce(or_, [getattr(slave, field) for slave in slaves]))) | ||||
|                     else: | ||||
|                         raise TypeError | ||||
|             else: | ||||
|                 for slave in slaves: | ||||
|                     r += self_e.connect(getattr(slave, field), keep=keep, omit=omit) | ||||
|         return r | ||||
| 
 | ||||
|     def connect_flat(self, *slaves): | ||||
|         r = [] | ||||
|         iter_slaves = [slave.iter_flat() for slave in slaves] | ||||
|         for m_signal, m_direction in self.iter_flat(): | ||||
|             if m_direction == DIR_M_TO_S: | ||||
|                 for iter_slave in iter_slaves: | ||||
|                     s_signal, s_direction = next(iter_slave) | ||||
|                     assert(s_direction == DIR_M_TO_S) | ||||
|                     r.append(s_signal.eq(m_signal)) | ||||
|             elif m_direction == DIR_S_TO_M: | ||||
|                 s_signals = [] | ||||
|                 for iter_slave in iter_slaves: | ||||
|                     s_signal, s_direction = next(iter_slave) | ||||
|                     assert(s_direction == DIR_S_TO_M) | ||||
|                     s_signals.append(s_signal) | ||||
|                 r.append(m_signal.eq(reduce(or_, s_signals))) | ||||
|             else: | ||||
|                 raise TypeError | ||||
|         return r | ||||
| 
 | ||||
|     def __len__(self): | ||||
|         return layout_len(self.layout) | ||||
| 
 | ||||
|     def __repr__(self): | ||||
|         return "<Record " + ":".join(f[0] for f in self.layout) + " at " + hex(id(self)) + ">" | ||||
|  | @ -74,7 +74,8 @@ class AbstractValueTransformer(metaclass=ABCMeta): | |||
|             new_value = self.on_Slice(value) | ||||
|         elif type(value) is Part: | ||||
|             new_value = self.on_Part(value) | ||||
|         elif type(value) is Cat: | ||||
|         elif isinstance(value, Cat): | ||||
|             # Uses `isinstance()` and not `type() is` because nmigen.compat requires it. | ||||
|             new_value = self.on_Cat(value) | ||||
|         elif type(value) is Repl: | ||||
|             new_value = self.on_Repl(value) | ||||
|  |  | |||
|  | @ -2,6 +2,9 @@ import inspect | |||
| from opcode import opname | ||||
| 
 | ||||
| 
 | ||||
| __all__ = ["NameNotFound", "get_var_name"] | ||||
| 
 | ||||
| 
 | ||||
| class NameNotFound(Exception): | ||||
|     pass | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 whitequark
						whitequark