| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -65,6 +65,16 @@ class VerilogTransformer(Transformer): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if len(args) > 1 and isinstance(args[1], range): | 
					 | 
					 | 
					 | 
					        if len(args) > 1 and isinstance(args[1], range): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            l = [f'{args[0]}[{i}]' for i in args[1]] | 
					 | 
					 | 
					 | 
					            l = [f'{args[0]}[{i}]' for i in args[1]] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            return l if len(l) > 1 else l[0] | 
					 | 
					 | 
					 | 
					            return l if len(l) > 1 else l[0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        elif "'" in args[0]: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            width, rest = args[0].split("'") | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            width = int(width) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            base, const = rest[0], rest[1:] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            const = int(const, {'b': 2, 'd':10, 'h':16}[base.lower()]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            l = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            for _ in range(width): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                l.insert(0, "1'b1" if (const & 1) else "1'b0") | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                const >>= 1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            return l if len(l) > 1 else l[0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        else: | 
					 | 
					 | 
					 | 
					        else: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            return args[0] | 
					 | 
					 | 
					 | 
					            return args[0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -82,20 +92,24 @@ class VerilogTransformer(Transformer): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        if isinstance(args[0], range): | 
					 | 
					 | 
					 | 
					        if isinstance(args[0], range): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            rnge = args[0] | 
					 | 
					 | 
					 | 
					            rnge = args[0] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            args = args[1:] | 
					 | 
					 | 
					 | 
					            args = args[1:] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for sd in [SignalDeclaration(kind, signal, rnge) for signal in args]: | 
					 | 
					 | 
					 | 
					        return [SignalDeclaration(kind, signal, rnge) for signal in args] | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if kind != 'wire' or sd.basename not in self._signal_declarations: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                self._signal_declarations[sd.basename] = sd | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    def input(self, args): self.declaration("input", args) | 
					 | 
					 | 
					 | 
					    def input(self, args): return self.declaration("input", args) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    def output(self, args): self.declaration("output", args) | 
					 | 
					 | 
					 | 
					    def output(self, args): return self.declaration("output", args) | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    def inout(self, args): self.declaration("input", args)  # just treat as input | 
					 | 
					 | 
					 | 
					    def inout(self, args): return self.declaration("input", args)  # just treat as input | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    def wire(self, args): self.declaration("wire", args) | 
					 | 
					 | 
					 | 
					    def wire(self, args): return self.declaration("wire", args) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    def module(self, args): | 
					 | 
					 | 
					 | 
					    def module(self, args): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        c = Circuit(args[0]) | 
					 | 
					 | 
					 | 
					        c = Circuit(args[0]) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        positions = {} | 
					 | 
					 | 
					 | 
					        positions = {} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        pos = 0 | 
					 | 
					 | 
					 | 
					        pos = 0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        const_count = 0 | 
					 | 
					 | 
					 | 
					        const_count = 0 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        self._signal_declarations = {} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        for decls in args[2:]:  # pass 0: collect signal declarations | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            if isinstance(decls, list): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                if len(decls) > 0 and isinstance(decls[0], SignalDeclaration): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    for decl in decls: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        self._signal_declarations[decl.basename] = decl | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for intf_sig in args[1].children: | 
					 | 
					 | 
					 | 
					        for intf_sig in args[1].children: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            for name in self._signal_declarations[intf_sig].names: | 
					 | 
					 | 
					 | 
					            for name in self._signal_declarations[intf_sig].names: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                positions[name] = pos | 
					 | 
					 | 
					 | 
					                positions[name] = pos | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -107,7 +121,7 @@ class VerilogTransformer(Transformer): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                for p, s in stmt.pins.items(): | 
					 | 
					 | 
					 | 
					                for p, s in stmt.pins.items(): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    if self.tlib.pin_is_output(n.kind, p): | 
					 | 
					 | 
					 | 
					                    if self.tlib.pin_is_output(n.kind, p): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s)) | 
					 | 
					 | 
					 | 
					                        Line(c, (n, self.tlib.pin_index(stmt.type, p)), Node(c, s)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            elif stmt is not None and stmt.data == 'assign': | 
					 | 
					 | 
					 | 
					            elif hasattr(stmt, 'data') and stmt.data == 'assign': | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                assignments.append((stmt.children[0], stmt.children[1])) | 
					 | 
					 | 
					 | 
					                assignments.append((stmt.children[0], stmt.children[1])) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for sd in self._signal_declarations.values(): | 
					 | 
					 | 
					 | 
					        for sd in self._signal_declarations.values(): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if sd.kind == 'output' or sd.kind == 'input': | 
					 | 
					 | 
					 | 
					            if sd.kind == 'output' or sd.kind == 'input': | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -117,17 +131,6 @@ class VerilogTransformer(Transformer): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        c.io_nodes[positions[name]] = n | 
					 | 
					 | 
					 | 
					                        c.io_nodes[positions[name]] = n | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    if sd.kind == 'input': | 
					 | 
					 | 
					 | 
					                    if sd.kind == 'input': | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        Line(c, n, Node(c, name)) | 
					 | 
					 | 
					 | 
					                        Line(c, n, Node(c, name)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        def assign_wire(s1, s2): | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if s1 in c.forks: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                assert s2 not in c.forks, 'assignment between two driven signals' | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                Line(c, c.forks[s1], Node(c, s2)) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            elif s2 in c.forks: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                assert s1 not in c.forks, 'assignment between two driven signals' | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                Line(c, c.forks[s2], Node(c, s1)) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            elif s2.startswith("1'b"): | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                cnode = Node(c, f'__const{s2[3]}_{const_count}__', f'__const{s2[3]}__') | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                const_count += 1 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                Line(c, cnode, Node(c, s1)) | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for target, source in assignments:  # pass 1.5: process signal assignments | 
					 | 
					 | 
					 | 
					        for target, source in assignments:  # pass 1.5: process signal assignments | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            target_sigs = [] | 
					 | 
					 | 
					 | 
					            target_sigs = [] | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if not isinstance(target, list): target = [target] | 
					 | 
					 | 
					 | 
					            if not isinstance(target, list): target = [target] | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -144,7 +147,16 @@ class VerilogTransformer(Transformer): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                else: | 
					 | 
					 | 
					 | 
					                else: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    source_sigs.append(s) | 
					 | 
					 | 
					 | 
					                    source_sigs.append(s) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            for t, s in zip(target_sigs, source_sigs): | 
					 | 
					 | 
					 | 
					            for t, s in zip(target_sigs, source_sigs): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                assign_wire(t, s) | 
					 | 
					 | 
					 | 
					                if t in c.forks: | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    assert s not in c.forks, 'assignment between two driven signals' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    Line(c, c.forks[t], Node(c, s)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                elif s in c.forks: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    assert t not in c.forks, 'assignment between two driven signals' | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    Line(c, c.forks[s], Node(c, t)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                elif s.startswith("1'b"): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    cnode = Node(c, f'__const{s[3]}_{const_count}__', f'__const{s[3]}__') | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    const_count += 1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    Line(c, cnode, Node(c, t)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for stmt in args[2:]:  # pass 2: connect signals to readers | 
					 | 
					 | 
					 | 
					        for stmt in args[2:]:  # pass 2: connect signals to readers | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if isinstance(stmt, Instantiation): | 
					 | 
					 | 
					 | 
					            if isinstance(stmt, Instantiation): | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                for p, s in stmt.pins.items(): | 
					 | 
					 | 
					 | 
					                for p, s in stmt.pins.items(): | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -195,7 +207,7 @@ GRAMMAR = r""" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sigsel: name range? | concat | 
					 | 
					 | 
					 | 
					    sigsel: name range? | concat | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    concat: "{" sigsel ( "," sigsel )*  "}" | 
					 | 
					 | 
					 | 
					    concat: "{" sigsel ( "," sigsel )*  "}" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    _namelist: name ( "," name )* | 
					 | 
					 | 
					 | 
					    _namelist: name ( "," name )* | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    name: ( /[a-z_][a-z0-9_]*/i | /\\[^\t \r\n]+[\t \r\n]/i | /1'b0/i | /1'b1/i ) | 
					 | 
					 | 
					 | 
					    name: ( /[a-z_][a-z0-9_]*/i | /\\[^\t \r\n]+[\t \r\n]/i | /[0-9]+'[bdh][0-9a-f]+/i ) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    %import common.NEWLINE | 
					 | 
					 | 
					 | 
					    %import common.NEWLINE | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ |  "//" /(.)*/ NEWLINE | 
					 | 
					 | 
					 | 
					    COMMENT: /\/\*(\*(?!\/)|[^*])*\*\// | /\(\*(\*(?!\))|[^*])*\*\)/ |  "//" /(.)*/ NEWLINE | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    %ignore ( /\r?\n/ | COMMENT )+ | 
					 | 
					 | 
					 | 
					    %ignore ( /\r?\n/ | COMMENT )+ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |