Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Idiomatic CXXRTL bindings for Zig

License

NotificationsYou must be signed in to change notification settings

kivikakk/zxxrtl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CXXRTL bindings for Zig.

Example

ili9341spi uses this in combination withNiar to build a CXXRTL simulationwithAmaranth and Zig.

Setup

Note

This guide assumes you're driving the build from outside, and use Zig's buildsystem just to build the Zig parts and link the final object. This gives you alot of flexibility, but if you don't need it, you can simplify by bringing theCXXRTL object file building into yourbuild.zig too. Refer tozxxrtl'sbuild.zig for guidance.

Add zxxrtl to yourbuild.zig.zon:

zig fetch --save https://github.com/kivikakk/zxxrtl/archive/<commit>.tar.gz

Now let's add the import to yourbuild.zig. We'll take the CXXRTL object filelist as an option in thebuild() function:

constcxxrtl_o_paths=b.option([][]constu8,"cxxrtl_o_path","path to .o file to link against")orelse &[_][]constu8{"../build/cxxrtl/ili9341spi.o"};

We supply a default value for the object file paths --- it should match yourdevelopment environment. This is to ensure ZLS still works.

Then add the dependency, and import the module into your executable:

constzxxrtl_mod=b.dependency("zxxrtl", .{    .target=target,    .optimize=optimize,}).module("zxxrtl");exe.root_module.addImport("zxxrtl",zxxrtl_mod);

The last step is to link against the CXXRTL object files:

for (cxxrtl_o_paths)|cxxrtl_o_path| {exe.addObjectFile(b.path(cxxrtl_o_path));}

Specify Yosys' data dir

If you want to be able to specify the Yosys data dir from thezig build line,you can specify it when adding the zxxrtl dependency. Here we add an option,with a default fallback to actually callingyosys-config --datdir for ZLS orthe lazy:

constyosys_data_dir=b.option([]constu8,"yosys_data_dir","yosys data dir (per yosys-config --datdir)")orelse@import("zxxrtl").guessYosysDataDir(b);

Now adapt theb.dependency() call:

constzxxrtl_mod=b.dependency("zxxrtl", .{    .target=target,    .optimize=optimize,    .yosys_data_dir=yosys_data_dir,}).module("zxxrtl");

Usage

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);}

Cxxrtl.Object(T) is the basic interface to CXXRTL objects. It exposes twomethods:curr(Self) T, andnext(Self, T) void, which get the current value,and set the next value respectively.

There's also a helper,Cxxrtl.Sample(T), which is used for change detection indriver loops: you call itstick(Self) on every trigger edge, and then canquery itsprev andcurr values, and if it'sstable(Self). IfT == bool,you can also ask whether it'sfalling(Self),rising(Self),stable_low(Self) orstable_high(Self).

The following example is adapted from an SPI peripheral blackbox. Each byte ofpayload from the design is specified as data or command depending on thedcline during the last bit. The module returns events to the caller on each tick.

conststd=@import("std");constCxxrtl=@import("zxxrtl");constSpiConnector=@This();clk:Cxxrtl.Sample(bool),res:Cxxrtl.Sample(bool),dc:Cxxrtl.Sample(bool),copi:Cxxrtl.Sample(bool),sr:u8=0,index:u8=0,constTick=union(enum) {Nop,Command:u8,Data:u8,};pubfninit(cxxrtl:Cxxrtl)SpiConnector {constclk=Cxxrtl.Sample(bool).init(cxxrtl,"spi_clk",false);constres=Cxxrtl.Sample(bool).init(cxxrtl,"spi_res",false);constdc=Cxxrtl.Sample(bool).init(cxxrtl,"spi_dc",false);constcopi=Cxxrtl.Sample(bool).init(cxxrtl,"spi_copi",false);return .{        .clk=clk,        .res=res,        .dc=dc,        .copi=copi,    };}pubfntick(self:*SpiConnector)Tick {constclk=self.clk.tick();constres=self.res.tick();constdc=self.dc.tick();constcopi=self.copi.tick();varresult:Tick=.Nop;if (res.curr) {self.sr=0;self.index=0;    }if (clk.rising()) {self.sr= (self.sr<<1)|@as(u8, (if (copi.curr)1else0));if (self.index<7)self.index+=1elseif (dc.curr) {result= .{ .Command=self.sr };self.index=0;        }else {result= .{ .Data=self.sr };self.index=0;        }    }returnresult;}

This is a very simple use case. For a relatively overcomplicated one, seesh1107'sI2CConnector.

About

Idiomatic CXXRTL bindings for Zig

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

[8]ページ先頭

©2009-2025 Movatter.jp