<commit_before>from python_toolkit.arrayQuery import where, distinctBy
from hdl_toolkit.hdlObjects.architecture import Architecture
from hdl_toolkit.hdlObjects.component import  Component
from hdl_toolkit.hdlObjects.entity import Entity
from hdl_toolkit.hdlObjects.process import HWProcess
from hdl_toolkit.synthetisator.rtlLevel.codeOp import If
from hdl_toolkit.synthetisator.rtlLevel.signal import Signal, SyncSignal
from hdl_toolkit.hdlObjects.portConnection import PortConnection
from hdl_toolkit.synthetisator.rtlLevel.utils import portItemfromSignal
from hdl_toolkit.synthetisator.rtlLevel.signalWalkers import  walkUnitInputs, walkSignalsInExpr, \
    discoverSensitivity, walkSigSouces, signalHasDriver
from hdl_toolkit.hdlObjects.typeDefs import BIT
from hdl_toolkit.hdlObjects.value import Value
from hdl_toolkit.hdlObjects.assignment import Assignment

from hdl_toolkit.synthetisator.templates import VHDLTemplates  
from hdl_toolkit.synthetisator.exceptions import SigLvlConfErr
from hdl_toolkit.hdlObjects.operator import Operator
from hdl_toolkit.hdlObjects.operatorDefs import AllOps


class Context():
    """
    Container for signals and units
    @ivar signals: dict of all signals in context
    @ivar startsOfDataPaths: is created by discover(interfaces), is set of nodes where datapaths starts
    @ivar subUnits:           --------------||---------------------------- all units in this context 
    """
    def __init__(self, name, globalNames:dict=None):
        """
        @param name: name of context is synthetized as entity name
        @param globalNames: dictionary of parameters is synthetized as entity generics  
        """
        if not globalNames:
            self.globals = {}
        else:
            self.globals = globalNames
        self.signals = {}
        self.name = name

    
    def sig(self, name, typ=BIT, clk=None, syncRst=None, defVal=None):
        """
        generate new signal in context
        @param clk: clk signal, if specified signal is synthetized as SyncSignal
        @param syncRst: reset 
        """

        if name in self.signals:
            raise Exception('signal name "%s" is not unique' % (name))
        if defVal is not None and not isinstance(defVal, Value):
            defVal = Value.fromPyVal(defVal, typ)

        if clk is not None:
            s = SyncSignal(name, typ, defVal)
            if syncRst is not None and defVal is None:
                raise Exception("Probably forgotten default value on sync signal %s", name)
            if syncRst is not None:
                r = If(syncRst.opIsOn(),
                            [Signal.assignFrom(s, defVal)] ,
                            [Signal.assignFrom(s, s.next)])
            else:
                r = [Signal.assignFrom(s, s.next)]
            
            If(clk.opOnRisigEdge(), r)
        else:
            if syncRst:
                raise SigLvlConfErr("Signal %s has reset but has no clk" % name)
            s = Signal(name, typ, defaultVal=defVal)
        self.signals[name] = s
        return s
    
    def cloneSignals(self, signals:list, oldToNewNameFn, cloneAsSync=False):
        buff = []
        for s in signals:
            buff.append(self.sig(oldToNewNameFn(s.name), s.vat_type.width))
        return buff
    
    def discover(self, interfaces):
        self.startsOfDataPaths = set()
        self.subUnits = set()
        def discoverDatapaths(signal):
            for node in walkSigSouces(signal):
                if node in self.startsOfDataPaths:
                    return 
                self.startsOfDataPaths.add(node)
                if isinstance(node, PortConnection) and not node.unit.discovered:
                    node.unit.discovered = True
                    for s in walkUnitInputs(node.unit):
                        discoverDatapaths(s)
                    self.subUnits.add(node.unit)
                elif isinstance(node, Operator):
                    assert(node.operator == AllOps.INDEX)
                    discoverDatapaths(node.result)
                elif isinstance(node, Assignment):
                    for s in walkSignalsInExpr(node.src):
                        discoverDatapaths(s)
                    assert(isinstance(node.cond, set))
                    for c in node.cond:
                        for s in  walkSignalsInExpr(c):
                            discoverDatapaths(s)
                        
            if signal in interfaces:
                self.startsOfDataPaths.add(signal)
                
        for s in where(interfaces, lambda s: signalHasDriver(s)):  # walk my outputs
            discoverDatapaths(s)
    
    def synthetize(self, interfaces):
        ent = Entity()
        ent.name = self.name

        # create generics
        ent.ctx = self.globals
        for _, v in self.globals.items():
            ent.generics.append(v)
        
        # create ports
        for s in interfaces:
            # s.dtype.ctx = ent.ctx
            ent.ports.append(portItemfromSignal(s))
   
        self.discover(interfaces)
        
        arch = Architecture(ent)
        # for s in where(arch.statements, lambda x: isinstance(x, PortConnection)):  # find subUnits
        #    self.subUnits.add(self.unit)
        assigments = list(where(self.startsOfDataPaths, lambda x: isinstance(x, Assignment)))
        for sig in set(map(lambda x:x.dst, assigments)):
            dps = list(where(assigments, lambda x: x.dst == sig))
            p = HWProcess("assig_process_" + sig.name)
            for dp in dps:
                p.sensitivityList.update(map(lambda x: x.name, discoverSensitivity(dp)))
            p.bodyBuff.extend(dps) 
            arch.processes.append(p)

        # add signals, variables etc. in architecture
        for _, s in self.signals.items():
            if s not in interfaces:
                # [TODO] if has driver
                arch.variables.append(s)
                if isinstance(s, SyncSignal):
                    arch.variables.append(s.next)
        
        # instanciate subUnits in architecture
        for u in self.subUnits:  
            arch.componentInstances.append(u.asVHDLComponentInstance(u._name)) 
        
        # add components in architecture    
        for su in distinctBy(self.subUnits, lambda x: x.name):
            c = Component(su)<commit_msg>fix: instance name now with _suffix to prevent name colision with entities/components<commit_after>from python_toolkit.arrayQuery import where, distinctBy
from hdl_toolkit.hdlObjects.architecture import Architecture
from hdl_toolkit.hdlObjects.component import  Component
from hdl_toolkit.hdlObjects.entity import Entity
from hdl_toolkit.hdlObjects.process import HWProcess
from hdl_toolkit.synthetisator.rtlLevel.codeOp import If
from hdl_toolkit.synthetisator.rtlLevel.signal import Signal, SyncSignal
from hdl_toolkit.hdlObjects.portConnection import PortConnection
from hdl_toolkit.synthetisator.rtlLevel.utils import portItemfromSignal
from hdl_toolkit.synthetisator.rtlLevel.signalWalkers import  walkUnitInputs, walkSignalsInExpr, \
    discoverSensitivity, walkSigSouces, signalHasDriver
from hdl_toolkit.hdlObjects.typeDefs import BIT
from hdl_toolkit.hdlObjects.value import Value
from hdl_toolkit.hdlObjects.assignment import Assignment

from hdl_toolkit.synthetisator.templates import VHDLTemplates  
from hdl_toolkit.synthetisator.exceptions import SigLvlConfErr
from hdl_toolkit.hdlObjects.operator import Operator
from hdl_toolkit.hdlObjects.operatorDefs import AllOps


class Context():
    """
    Container for signals and units
    @ivar signals: dict of all signals in context
    @ivar startsOfDataPaths: is created by discover(interfaces), is set of nodes where datapaths starts
    @ivar subUnits:           --------------||---------------------------- all units in this context 
    """
    def __init__(self, name, globalNames:dict=None):
        """
        @param name: name of context is synthetized as entity name
        @param globalNames: dictionary of parameters is synthetized as entity generics  
        """
        if not globalNames:
            self.globals = {}
        else:
            self.globals = globalNames
        self.signals = {}
        self.name = name

    
    def sig(self, name, typ=BIT, clk=None, syncRst=None, defVal=None):
        """
        generate new signal in context
        @param clk: clk signal, if specified signal is synthetized as SyncSignal
        @param syncRst: reset 
        """

        if name in self.signals:
            raise Exception('signal name "%s" is not unique' % (name))
        if defVal is not None and not isinstance(defVal, Value):
            defVal = Value.fromPyVal(defVal, typ)

        if clk is not None:
            s = SyncSignal(name, typ, defVal)
            if syncRst is not None and defVal is None:
                raise Exception("Probably forgotten default value on sync signal %s", name)
            if syncRst is not None:
                r = If(syncRst.opIsOn(),
                            [Signal.assignFrom(s, defVal)] ,
                            [Signal.assignFrom(s, s.next)])
            else:
                r = [Signal.assignFrom(s, s.next)]
            
            If(clk.opOnRisigEdge(), r)
        else:
            if syncRst:
                raise SigLvlConfErr("Signal %s has reset but has no clk" % name)
            s = Signal(name, typ, defaultVal=defVal)
        self.signals[name] = s
        return s
    
    def cloneSignals(self, signals:list, oldToNewNameFn, cloneAsSync=False):
        buff = []
        for s in signals:
            buff.append(self.sig(oldToNewNameFn(s.name), s.vat_type.width))
        return buff
    
    def discover(self, interfaces):
        self.startsOfDataPaths = set()
        self.subUnits = set()
        def discoverDatapaths(signal):
            for node in walkSigSouces(signal):
                if node in self.startsOfDataPaths:
                    return 
                self.startsOfDataPaths.add(node)
                if isinstance(node, PortConnection) and not node.unit.discovered:
                    node.unit.discovered = True
                    for s in walkUnitInputs(node.unit):
                        discoverDatapaths(s)
                    self.subUnits.add(node.unit)
                elif isinstance(node, Operator):
                    assert(node.operator == AllOps.INDEX)
                    discoverDatapaths(node.result)
                elif isinstance(node, Assignment):
                    for s in walkSignalsInExpr(node.src):
                        discoverDatapaths(s)
                    assert(isinstance(node.cond, set))
                    for c in node.cond:
                        for s in  walkSignalsInExpr(c):
                            discoverDatapaths(s)
                        
            if signal in interfaces:
                self.startsOfDataPaths.add(signal)
                
        for s in where(interfaces, lambda s: signalHasDriver(s)):  # walk my outputs
            discoverDatapaths(s)
    
    def synthetize(self, interfaces):
        ent = Entity()
        ent.name = self.name

        # create generics
        ent.ctx = self.globals
        for _, v in self.globals.items():
            ent.generics.append(v)
        
        # create ports
        for s in interfaces:
            # s.dtype.ctx = ent.ctx
            ent.ports.append(portItemfromSignal(s))
   
        self.discover(interfaces)
        
        arch = Architecture(ent)
        # for s in where(arch.statements, lambda x: isinstance(x, PortConnection)):  # find subUnits
        #    self.subUnits.add(self.unit)
        assigments = list(where(self.startsOfDataPaths, lambda x: isinstance(x, Assignment)))
        for sig in set(map(lambda x:x.dst, assigments)):
            dps = list(where(assigments, lambda x: x.dst == sig))
            p = HWProcess("assig_process_" + sig.name)
            for dp in dps:
                p.sensitivityList.update(map(lambda x: x.name, discoverSensitivity(dp)))
            p.bodyBuff.extend(dps) 
            arch.processes.append(p)

        # add signals, variables etc. in architecture
        for _, s in self.signals.items():
            if s not in interfaces:
                # [TODO] if has driver
                arch.variables.append(s)
                if isinstance(s, SyncSignal):
                    arch.variables.append(s.next)
        
        # instanciate subUnits in architecture
        for u in self.subUnits:  
            arch.componentInstances.append(u.asVHDLComponentInstance(u._name + "_inst")) 
        
        # add components in architecture    
        for su in distinctBy(self.subUnits, lambda x: x.name):
            c = Component(su)
{'fraction_non_alphanumeric': 0.08422124725791288, 'fraction_numerical': 0.0, 'mean_word_length': 1.9789964994165694, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5002808', 'n_tokens_mistral': 3621, 'n_tokens_neox': 3482, 'n_words': 937}