from hdl_toolkit.simulator.agentBase import SyncAgentBase
from hdl_toolkit.hdlObjects.specialValues import NOP


class HandshakedAgent(SyncAgentBase):
    def __init__(self, intf, clk=None, rstn=None):
        super().__init__(intf, clk=None, rstn=None)
        self.actualData = NOP
        self.data = []
        # these signals are extracted like this to make 
        # agent more configurable
        self._rd = self.getRd()
        self._vld = self.getVld()
    
    def getRd(self):
        """get "ready" signal"""
        return self.intf.rd
    
    def getVld(self):
        """get "valid" signal"""
        return self.intf.vld
        
    def monitor(self, s):
        """
        Collect data
        """
        if s.r(self.rst_n).val and self.enable:
            vld = s.r(self._vld).val
            if vld:
                d = self.doRead(s)
                self.data.append(d)
            s.w(1, self._rd)
        else:
            s.w(0, self._rd)
    
    def doRead(self, s):
        return s.read(self.intf.data)
        
    def doWrite(self, s, data):
        s.w(data, self.intf.data)
        
    def driver(self, s):
        if self.actualData is NOP and self.data:
            self.actualData = self.data.pop(0)
        
        do = self.actualData is not NOP
        
        if do:
            self.doWrite(s, self.actualData)
        else:
            self.doWrite(s, None)
            
        if s.r(self.rst_n).val and do and self.enable:
            s.w(1, self._vld)
        else:
            s.w(0, self._vld)
            return
        
        yield s.updateComplete
        
        rd = s.r(self._rd).val
        if rd:
            if self.data:
                self.actualData = self.data.pop(0)
            else:
                self.actualData = NOP

class HandshakeSyncAgent(HandshakedAgent):
    def doWrite(self, s, data):
        pass
    
    def doRead(self, s):
        raise NotImplementedError()    
    

@@ -753,32 +753,109 @@
 nd self.enable:%0A
+            s.w(1, self._rd)%0A            %0A            yield s.updateComplete%0A
             vld 
@@ -870,20 +870,16 @@
 lf._vld)
-.val
 %0A       
@@ -889,16 +889,39 @@
   if vld
+.val or not vld.vldMask
 :%0A      
@@ -989,37 +989,8 @@
 (d)%0A
-            s.w(1, self._rd)%0A
     
@@ -1703,20 +1703,17 @@
 elf._rd)
-.val
+ 
 %0A       
@@ -1718,16 +1718,38 @@
    if rd
+.val or not rd.vldMask
 :%0A      

send data on undfined state of controll signals