Closed nmigen-issue-migration closed 4 years ago
Comment by whitequark Thursday Sep 26, 2019 at 02:16 GMT
This is currently broken for reasons that are not entirely clear. See #28. I plan to rewrite the simulator entirely, since it has a number of serious flaws that require changing core decisions, but this will take some time.
A possible workaround is to use EnableInserter
to sequence the pos
and neg
actions, and then DomainRenamer
to map them both to a single sync
domain.
Another possible workaround is to use https://github.com/andresdemski/nmigen-cocotb. (I have not personally used it.) I will also take a good look at cocotb's user interface (see #228), so if later you want to get rid of cocotb in favor of Python-only simulation, it is likely that the migration would not be very painful.
Comment by whitequark Saturday Oct 12, 2019 at 23:32 GMT
@RobertBaruch Have you been able to use one of these workarounds?
Comment by RobertBaruch Sunday Oct 13, 2019 at 13:52 GMT
I haven't looked at it yet. I can try nmigen-cocotb.
Comment by RobertBaruch Sunday Oct 13, 2019 at 16:15 GMT
Tried nmigen-cocotb, but apparently nothing is output. I get a sim_build directory with a vvp file. I did run vvp on that vvp file and got an output.vcd, which contained no signal changes. Maybe there's some documentation out of date -- the test runner doesn't seem to run the function annotated with @cocotb.test()
.
from nmigen import *
# from nmigen.cli import main
from nmigen.asserts import *
# from nmigen.back import pysim
# from nmigen.hdl.ast import Tick
# module edgelord outputs the state of the clock without using
# the clock in combinatorial logic. This is a good thing in
# FPGAs, where the clock is a special signal that might get
# badly routed if it has to go through anything other than the
# clock inputs of flipflops.
#
# The reset signal MUST be held high for both edges,
# otherwise the clk_state will be inverted.
class Edgelord(Elaboratable):
def __init__(self):
self.clk_state = Signal()
self.unfunf = Signal()
def elaborate(self, platform):
pos = Signal()
neg = Signal()
rst = ResetSignal("pos")
m = Module()
# Verilog equivalent:
#
# assign clk_state = reset || !(pos ^ neg);
m.d.comb += self.clk_state.eq(rst | ~(pos ^ neg))
# Verilog equivalent:
#
# always @(posedge clk) begin
# if (reset) pos <= 0;
# else pos <= !(pos ^ clk_state);
# end
#
# always @(negedge clk) begin
# if (reset) neg <= 0;
# else neg <= neg ^ clk_state;
# end
m.d.neg += self.unfunf.eq(~self.unfunf)
with m.If(rst):
m.d.pos += pos.eq(0)
m.d.neg += neg.eq(0)
with m.Else():
m.d.pos += pos.eq(~(pos ^ self.clk_state))
m.d.neg += neg.eq(neg ^ self.clk_state)
return m
from nmigen_cocotb import run, get_current_module
import cocotb
from cocotb.triggers import Timer
def tick(dut):
print("tick\n")
dut.clk <= 0
yield Timer(10, 'ns')
dut.clk <= 1
yield Timer(10, 'ns')
@cocotb.test()
def reset_test(dut):
print("start reset_test\n")
dut._log.info("Running test!")
dut.rst <= 1
tick(dut)
tick(dut)
dut.rst <= 0
tick(dut)
tick(dut)
tick(dut)
dut._log.info("Test complete!")
def test_module():
clk = Signal()
rst = Signal()
pos = ClockDomain()
pos.clk = clk
pos.rst = rst
neg = ClockDomain(clk_edge="neg")
neg.clk = clk
neg.rst = rst
edgelord = Edgelord()
m = Module()
m.domains.pos = pos
m.domains.neg = neg
m.submodules.edgelord = edgelord
print("Start run\n")
run(m, get_current_module(), ports=[clk, rst, edgelord.clk_state], vcd_file='output.vcd')
if __name__ == "__main__":
print("Running\n")
test_module()
$ python3 edgelord.py cocotb -m test -v output.vcd
Running
Start run
top [(sig clk), (sig rst), (sig clk_state)]
iverilog -o /mnt/c/Users/rober/Documents/mz80/mz80/core/sim_build/top.vvp -D COCOTB_SIM=1 -s top -g2012 -s cocotb_waveform_module /tmp/tmpeot_rz96/nmigen_output.v
vvp -M /home/robertbaruch/.local/lib/python3.6/site-packages/cocotb_test/libs/icarus -m libvpi /mnt/c/Users/rober/Documents/mz80/mz80/core/sim_build/top.vvp
-.--ns INFO cocotb.gpi ../embed/gpi_embed.c:111 in embed_init_python Did not detect Python virtual environment. Using system-wide Python interpreter.
-.--ns INFO cocotb.gpi ../gpi/GpiCommon.cpp:91 in gpi_print_registered_impl VPI registered
0.00ns INFO cocotb __init__.py:131 in _initialise_testbench Running tests with Cocotb v1.2.0 from Unknown
0.00ns INFO cocotb __init__.py:148 in _initialise_testbench Seeding Python random module with 1570983084
0.00ns INFO cocotb.regression regression.py:210 in tear_down Passed 0 tests (0 skipped)
0.00ns INFO cocotb.regression regression.py:392 in _log_sim_summary *************************************************************************************
** ERRORS : 0 **
*************************************************************************************
** SIM TIME : 0.00 NS **
** REAL TIME : 0.00 S **
** SIM / REAL TIME : 0.00 NS/S **
*************************************************************************************
0.00ns INFO cocotb.regression regression.py:219 in tear_down Shutting down...
$ vvp sim_build top.vvp
Comment by RobertBaruch Sunday Oct 13, 2019 at 16:20 GMT
Hmm, the coctb-nmigen example doesn't even output anything, so there must be some step missing.
Comment by RobertBaruch Sunday Oct 13, 2019 at 16:43 GMT
Yeah, no.
$ vvp -M /home/robertbaruch/.local/lib/python3.6/site-packages/cocotb_test/libs/icarus -m libvpi /mnt/c/Users/rober/Documents/mz80/mz80/core/sim_build/top.vvp
-.--ns INFO cocotb.gpi ../embed/gpi_embed.c:111 in embed_init_python Did not detect Python virtual environment. Using system-wide Python interpreter.
-.--ns INFO cocotb.gpi ../gpi/GpiCommon.cpp:91 in gpi_print_registered_impl VPI registered
AttributeError: module 'cocotb' has no attribute 'loggpi'
Error in sys.excepthook:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 63, in apport_excepthook
from apport.fileutils import likely_packaged, get_recent_crashes
File "/usr/lib/python3/dist-packages/apport/__init__.py", line 5, in <module>
from apport.report import Report
File "/usr/lib/python3/dist-packages/apport/report.py", line 30, in <module>
import apport.fileutils
File "/usr/lib/python3/dist-packages/apport/fileutils.py", line 23, in <module>
from apport.packaging_impl import impl as packaging
File "/usr/lib/python3/dist-packages/apport/packaging_impl.py", line 23, in <module>
import apt
File "/usr/lib/python3/dist-packages/apt/__init__.py", line 23, in <module>
import apt_pkg
ModuleNotFoundError: No module named 'apt_pkg'
Original exception was:
AttributeError: module 'cocotb' has no attribute 'loggpi'
Failed to to get simlog object
Segmentation fault (core dumped)
Comment by RobertBaruch Sunday Oct 13, 2019 at 17:05 GMT
Sorry, I'm going to need more explicit instructions on what to do with EnableInserter
and DomainRenamer
.
Comment by whitequark Sunday Oct 13, 2019 at 17:09 GMT
Something like:
m = Module()
phase = Signal()
m.d.sync += phase.eq(~phase)
design = EnableInserter({"pos":~phase,"neg":phase})(design)
design = DomainRenamer({"pos":"sync","neg":"sync"})(design)
m.submodules += design
Comment by andresdemski Thursday Oct 17, 2019 at 16:12 GMT
Hi, get_current_module function is not working currently in nmigen-cocotb. Try to use it with harcoded module. Try this commit: https://github.com/andresdemski/nmigen-cocotb/tree/9e5d868587c859820147365a51d38f60e459cbb0
Issue by RobertBaruch Thursday Sep 26, 2019 at 02:12 GMT Originally opened as https://github.com/m-labs/nmigen/issues/236
What's the right pattern to use? Here is an example of what I've tried:
This resulted in: