After the better part of 20 years working with Python, it still managed to
surprise me today.
I’m so used to languages treating x += y et al. as pure sugar for x = x + y
that it skipped my mind that some don’t.
I’m not surprised that you can override them separately in some languages (e.g.
I simply assume this to be the case in C++, and on checking it turns out to
be true — but that seems fair enough given the scope of the language), but I
really am so accustomed to them being only sugar in Ruby that I assumed the same
would hold, at least in effect, in Python.
Thus my surprise on some_list += x modifying some_list in place (unlike
some_list = some_list + x), but once observed, I realised there’d be a
separately-overridden operator function — namely __iadd__ — and so I
figured it “had” to be that way.
Or did it? I then found myself assuming it’s because these operators can’t
actually reassign the receiver, but in fact they can and do: the return value is
what’s assigned to the LHS. So it’s just a matter of convention.
I’ve been getting back into using CXXRTL and Zig together, so I’ve extracted
and rendered somewhat reusable the bindings I made to use them together!
zxxrtl uses CXXRTL’s C API to provide a somewhat idiomatic way to access,
manipulate, and respond to events happening in the design. Its README covers the
setup — it’s a bit involved as it’s necessarily something of a build system,
but once you’re done it’s good to go and flexible enough to be instrumented from
a higher build system.
I’m going to paste the example usage here; this doesn’t use the Sample API for
edge detection, and just drives the simulation while optionally recording VCD:
constCxxrtl=@import("zxxrtl");// Initialise the design.constcxxrtl=Cxxrtl.init();// Optionally start recording VCD. Assume `vcd_out` is `?[]const u8` representing an// optional output filename.varvcd:?Cxxrtl.Vcd=null;if(vcd_out!=null)vcd=Cxxrtl.Vcd.init(cxxrtl);defer{if(vcd)|*vcdh|vcdh.deinit();cxxrtl.deinit();}// Get handles to the clock and reset lines.constclk=cxxrtl.get(bool,"clk");constrst=cxxrtl.get(bool,"rst");// These are of type `Cxxrtl.Object(bool)`.// Reset for a tick.rst.next(true);clk.next(false);cxxrtl.step();if(vcd)|*vcdh|vcdh.sample();clk.next(true);cxxrtl.step();if(vcd)|*vcdh|vcdh.sample();rst.next(false);// Play out 10 cycles.for(0..10)|_|{clk.next(false);cxxrtl.step();if(vcd)|*vcdh|vcdh.sample();clk.next(true);cxxrtl.step();if(vcd)|*vcdh|vcdh.sample();}if(vcd)|*vcdh|{// Assume `alloc` exists.constbuffer=tryvcdh.read(alloc);deferalloc.free(buffer);varfile=trystd.fs.cwd().createFile(vcd_out.?,.{});deferfile.close();tryfile.writeAll(buffer);}
I gave a lightning talk at last night’s Yosys Users Group about combining
Chisel and C++ with Yosys/CXXRTL. I think there’ll be a recording
of them that goes up on YouTube eventually?