kivikakk.ee

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.

sint

Notes.app, kell 08:03:

my new theory is that satan Crept into this world through signed integers

zxxrtl

digital

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:

const Cxxrtl = @import("zxxrtl");

// Initialise the design.
const cxxrtl = Cxxrtl.init();

// Optionally start recording VCD. Assume `vcd_out` is `?[]const u8` representing an
// optional output filename.
var vcd: ?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.
const clk = cxxrtl.get(bool, "clk");
const rst = 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.
    const buffer = try vcdh.read(alloc);
    defer alloc.free(buffer);

    var file = try std.fs.cwd().createFile(vcd_out.?, .{});
    defer file.close();

    try file.writeAll(buffer);
}

Hopefully this is useful to someone else!

Identities changed to protect the innocent.

<pestopasta> How do you do 128bit memory buses and stuff like that
<pestopasta> Like what is going on in those 128 bits
<Rice> uh, data that's being read from or written to memory?
<Rice> What is the issue you're not understanding
<pestopasta> @Rice What is transferred over it
<HamSandwich> data that's being read from or written to memory 👀
<pestopasta> @HamSandwich Yea. How do you manage 128 bits though. That's a lot
<HamSandwich> They are written to and from caches via the cache controller, not the core. The core has a maximum of 32-bit access.
<Rice> @pestopasta ...the same way you handle 32 or 64 bits of data, just double or quadruple?
<pestopasta> I don't know what you mean. Is there a video explaining this?