The former 'jupyosys' fork from myHDL is in process of migrating into this development tree.
Status notes:
import sys
sys.path.insert(0, "../..")
from myirl.emulation.myhdl import *
Byte = Signal.Type(intbv, 8)
Bool = Signal.Type(bool)
@block
def lfsr8(clk : ClkSignal, ce : Bool, reset : ResetSignal, dout : Byte.Output,
RVAL : int = 1):
"""LFSR with all states"""
v = Signal(intbv(RVAL)[8:])
fb = Signal(bool())
e = v[7:0] == 0
@always_seq(clk.posedge, reset)
def worker():
if ce == 1:
v.next = concat(v[6], v[5], v[4], v[3] ^ fb, v[2] ^ fb, v[1] ^ fb, v[0], fb)
@always_comb
def assign():
fb.next = v[7] ^ e
dout.next = v
return instances()
# Wrapper hack to use local dictionary for instance naming
def use_local_names(arg):
arg.use_local_names = True
return arg
@use_local_names
@block
def unit_count(clk : ClkSignal, ce: Signal, reset : ResetSignal, q : Signal.Output):
c, d = [ Signal(intbv(0)[8:]) for _ in range(2) ]
inst_lfsr = lfsr8(clk, ce, reset, d, RVAL = 0xfa)
@always_seq(clk.posedge, reset)
def counter():
c.next = c + 1
# q.next = d ^ c
wires = [ q.wireup(d ^ c) ]
return instances()
from myirl.targets import pyosys
def test_expr(tgt):
ce = Signal(bool())
clk = ClkSignal()
reset = ResetSignal(0, 1, isasync = True)
q = Signal(intbv()[8:])
t = unit_count(clk, ce, reset, q)
designs = t.elab(tgt, elab_all = True)
return designs[0]
tgt = pyosys.RTLIL("top")
design = test_expr(tgt)
design.display_rtl(selection = "unit_count", fmt='dot')
# design.display_rtl(selection = "lfsr8", fmt='dot')
FALLBACK: UNHANDLED ROOT CLASS <class 'ipykernel.zmqshell.ZMQInteractiveShell'>, create new context Elaborating component lfsr8_s1_s1_s1_s8_250 Adding module with name `lfsr8` Adding module with name `unit_count` FINALIZE implementation `unit_count` of `unit_count` -- Running command `tee -q hierarchy -top \unit_count' -- -- Running command `show -format dot -prefix top unit_count' -- 2. Generating Graphviz representation of design. Writing dot description to `top.dot'. Dumping module unit_count to page 1.
The @use_local_names
construct sets the myHDL instance variable names for the identifier.
Note: Pan and zoom may not work on some browsers.
from yosys import display
display.display_dot(design.name)
Note that and
, or
and not
boolean constructs are no longer allowed with signals.
from simulation import *
from yosys.simulator import CXXRTL as Sim
@sim.testbench(Sim, time_unit = 'ns')
def testbench():
clk = ClkSignal(init = 0)
reset = ResetSignal(1, 1, isasync = False)
ce = Signal(bool())
a = Signal(intbv()[8:])
inst = unit_count(clk, ce, reset, a)
@always(delay(2))
def clkgen():
clk.next = ~ clk
@sequence
def reset_seq():
yield delay(21)
reset.next = False
yield delay(1)
ce.next = True
yield delay(20)
return instances()
The simulation is executed using the .run
method below. Note that the simulation may not be fully 'delta' accurate and will only serve for synchronous designs.
Note: It is mandatory to yield an initial delay in the sequential code to properly arm the concurrent process scheduling.
def test_simulation(n):
t = testbench()
assert t._uut.obj.ctx == unit_count.ctx
t.run(n)
return t
t = test_simulation(2000)
FALLBACK: UNHANDLED ROOT CLASS <class 'yosys.simulator._CXXRTL_Testbench'>, create new context Module unit_count: Existing instance unit_count, rename to unit_count_1 Module unit_count: Existing instance lfsr8, rename to lfsr8_1 Elaborating component lfsr8_s1_s1_s1_s8_250 Adding module with name `lfsr8_1` Adding module with name `unit_count_1` FINALIZE implementation `unit_count_1` of `unit_count` Compiling /tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f.pyx because it changed. [1/1] Cythonizing /tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f.pyx running build_ext building 'unit_count_1_468f' extension creating build/temp.linux-x86_64-3.9/tmp/myirl_unit_count_s99a9uf8 x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=unit_count_1_468f -I../../myirl/../ -I/tmp/myirl_unit_count_s99a9uf8/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f.cpp -o build/temp.linux-x86_64-3.9/tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f.o x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -DCOSIM_NAMESPACE=unit_count_1_468f -I../../myirl/../ -I/tmp/myirl_unit_count_s99a9uf8/ -I/usr/share/yosys/include -I/usr/include/python3.9 -c /tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f_rtl.cpp -o build/temp.linux-x86_64-3.9/tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f_rtl.o x86_64-linux-gnu-g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fwrapv -O2 -Wl,-z,relro -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-RNBry6/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.9/tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f.o build/temp.linux-x86_64-3.9/tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f_rtl.o -o build/lib.linux-x86_64-3.9/unit_count_1_468f.cpython-39-x86_64-linux-gnu.so copying build/lib.linux-x86_64-3.9/unit_count_1_468f.cpython-39-x86_64-linux-gnu.so -> Open for writing: testbench.vcd DEBUG STOP PROCESS reset_seq
The resulting test bench file: testbench.vcd
When the .elab()
method is called, the design is elaborated as RTLIL and a list of design elements is returned, the first being a RTLIL Design handle.
The .finalize()
method is called last inside elaboration, which can perform some optimizations or emissions to specific targets.
class MyRTL(pyosys.RTLIL):
def finalize(self, top, objs = None):
tname = top.name
design = self._design
design.run("hierarchy -top %s" % tname)
print(80 * '=')
design.write_verilog(name = top.obj.name)
design.run("flatten; ls; select %s; stat" % tname)
return [design]
The .finalize()
function must return the created elements in a list, which is in turn returned from the .elab()
call.
tgt = MyRTL("top2")
design = test_expr(tgt)
FALLBACK: UNHANDLED ROOT CLASS <class 'ipykernel.zmqshell.ZMQInteractiveShell'>, create new context Module unit_count: Existing instance unit_count, rename to unit_count_2 Module unit_count: Existing instance lfsr8, rename to lfsr8_2 Elaborating component lfsr8_s1_s1_s1_s8_250 Adding module with name `lfsr8_2` Adding module with name `unit_count_2` ================================================================================ -- Running command `tee -q hierarchy -top \unit_count_1' -- -- Running command `tee -q write_cxxrtl -namespace unit_count_1_468f -header /tmp/myirl_unit_count_s99a9uf8/unit_count_1_468f_rtl.cpp' -- -- Running command `tee -q hierarchy -top unit_count_2' -- -- Running command `ls; check' -- 6. Executing CHECK pass (checking for obvious problems). Found and reported 0 problems. -- Running command `hierarchy -check' -- 7. Executing HIERARCHY pass (managing design hierarchy). -- Running command `write_verilog unit_count_mapped.v' -- 8. Executing Verilog backend. Dumping module `\lfsr8_2'. Dumping module `\unit_count_2'. -- Running command `tee -q flatten; ls; select unit_count_2; stat' -- 1 modules: unit_count_2 10. Printing statistics.
!cat unit_count_mapped.v
/* Generated by Yosys 0.13+3 (git sha1 4656b0171, gcc 10.2.1-6 -Og -fPIC) */ module lfsr8_2(clk, ce, reset, dout); wire [7:0] _00_; wire [-1:0] _01_; wire _02_; wire _03_; wire _04_; wire _05_; wire [7:0] _06_; wire _07_; wire _08_; wire _09_; wire [7:0] _10_; reg [7:0] _11_; wire [7:0] _12_; wire [7:0] _13_; input ce; input clk; output [7:0] dout; wire fb; input reset; wire [7:0] v; assign _08_ = v[6:0] == 7'h00; assign _09_ = v[7] ^ _08_; assign _05_ = ce == 1'h1; assign _03_ = v[2] ^ fb; assign _04_ = v[3] ^ fb; assign _06_ = _05_ ? _00_ : _13_; assign _02_ = v[1] ^ fb; always @(posedge clk, posedge reset) if (reset) _11_ <= 8'hfa; else _11_ <= _06_; assign _00_ = { v[6:4], _04_, _03_, _02_, v[0], fb }; assign v = _11_; assign _13_ = _11_; assign _07_ = _09_; assign _10_ = v; assign fb = _07_; assign dout = _10_; endmodule (* top = 1 *) module unit_count_2(clk, ce, reset, q); wire [7:0] _0_; wire [8:0] _1_; wire [7:0] _2_; reg [7:0] _3_; wire [7:0] _4_; wire [7:0] c; input ce; input clk; wire [7:0] d; output [7:0] q; input reset; assign _2_ = d ^ c; assign _1_ = c + 8'h01; always @(posedge clk, posedge reset) if (reset) _3_ <= 8'h00; else _3_ <= _0_; lfsr8_2 inst_lfsr ( .ce(ce), .clk(clk), .dout(d), .reset(reset) ); assign _0_ = _1_[7:0]; assign c = _3_; assign q = _2_; endmodule
Some constructs that work for the VHDL target are not yet supported:
p[0].next = x