kivikakk.ee

sint

Notes.app, kell 08:03:

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

zxxrtl

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!

Täna

Täna oli saunapäev. ^_^