一起使用模拟 (MyHDL) 和 wxPython

发布于 2024-10-20 01:08:03 字数 1595 浏览 2 评论 0原文

我正在使用 MyHDL 包进行硬件模拟,但我想在它周围放置一个 GUI,以便用户可以交互式地更改信号并查看其他信号的更新。

问题是,MyHDL 使用模拟器,如下所示

  • 模拟器有多个生成器
  • 每个生成器可以监听信号变化,或者调用yield delay(x) 以告诉模拟器等待 x 个刻度再次调用它。
  • 调用 Simulator.run() 启动模拟循环
  • 运行循环直至完成

wxPython 显然使用了事件循环。因此,我显然无法在不捆绑另一个的情况下运行这两个。

我的第一个(愚蠢)方法如下,

    def Hack():
        @instance
        def inst():
            yield delay(1)
            self._app.MainLoop()
        return inst
    MyHack = Hack()
    self._instances.append(MyHack)
    self._simulator = Simulation(*self._instances)
    self._simulator.run()

这有效,但 inst() 生成器只会运行一次,因此模拟实际上什么也没做。

然后我意识到这是需要多线程的情况。我尝试了以下方法:

    self._simulator = Simulation(*self._instances)
    p = Process(target=StartSim, args=(self._simulator,))
    p.start()
    #self._simulator.run()
    self._app.MainLoop()
    p.join()

def StartSim(sim):
    sim.run()

但是当然我最初并没有考虑线程安全。此外,我在模拟器中拥有的所有生成器函数都无法传递给线程。

我想我可以花一些时间真正研究一个可靠的线程工作类,该类是较早创建的,并且可以通过某种消息传递以某种方式获得所需的生成器函数。然而,在我看来,如果我可以定义某种生成器,为 wxPython 循环的每一步调用“yield delay(1)”,那么事情会更容易。在课堂上是这样的:

def OnIdle(self):
    yield delay(10)

然后用我原来的方法。问题是,我需要的代码是这样的:

    def Hack():
        @instance
        def inst():
            self._app.InitMainLoop()
            while(self._app.InMainLoop())
                yield delay(1)
                self._app.DoMainLoopBody()
        return inst

那么,在冗长的解释之后,有没有一个好的方法来做到这一点?我可以定义自己的 MainLoop 或以某种方式更改它吗?或者有人曾经使用过 MyHDL 和线程吗?

I am using the package MyHDL to do hardware simulation, but I want to put a GUI around it so that users can interactively change signals and see the other signals update.

The problem is, MyHDL uses a simulator as follows

  • Simulator has several generators
  • Each generator can either be listening for signal changes, or call yield delay(x) in order to tell the simulator to wait to call it again for x ticks.
  • Call Simulator.run() to start loop of simulation
  • Runs loop to completion

wxPython obviously uses an event loop. Therefore, I clearly can't run both of these without tying the other one up.

My first (dumb) method was as follows

    def Hack():
        @instance
        def inst():
            yield delay(1)
            self._app.MainLoop()
        return inst
    MyHack = Hack()
    self._instances.append(MyHack)
    self._simulator = Simulation(*self._instances)
    self._simulator.run()

This worked, but the inst() generator would only run once, so the Simulation really did nothing.

Then I realized this was a situation that called for multithreading. I tried the following:

    self._simulator = Simulation(*self._instances)
    p = Process(target=StartSim, args=(self._simulator,))
    p.start()
    #self._simulator.run()
    self._app.MainLoop()
    p.join()

def StartSim(sim):
    sim.run()

But of course I didn't think about thread safety initially. Also, all of those generator functions I have in the simulator can't be passed to the thread.

I'm thinking I could spend some time really working on a solid thread worker class which gets created earlier and which can SOMEHOW get the generator functions needed via some kind of message passing. However, it seems to me like it would be way easier if I could define some kind of generator that will call "yield delay(1)" for every step of the wxPython loop. Something like this in a class:

def OnIdle(self):
    yield delay(10)

And then going with my original method. The problem is, I need the code to be something like this:

    def Hack():
        @instance
        def inst():
            self._app.InitMainLoop()
            while(self._app.InMainLoop())
                yield delay(1)
                self._app.DoMainLoopBody()
        return inst

So, after that long-winded explanation, is there a good way to do this? Can I define my own MainLoop or change it in some way? Or has anyone ever worked with MyHDL and threading?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十秒萌定你 2024-10-27 01:08:03

没关系,我使用 app.ExitLoop() “解决”了它,

我意识到我可以将自己的循环包裹在 app.MainLoop() 周围,每当我收到模拟器关心的事件时,处理程序都会调用 app.ExitLoop(),从而提供控制权返回到模拟器,然后它再次启动 wx 的主循环。

它并不完美,它绝对是一个黑客,但它正在工作

Nevermind, I "solved" it using app.ExitLoop()

I realized I could wrap my own loop around app.MainLoop() and whenever I get an event that the Simulator cares about, the handler calls app.ExitLoop(), giving control back to the simulator and then it starts the main loop for wx again.

It's not perfect, it's definitely a hack, but it's working

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文