Skip to content

Instantly share code, notes, and snippets.

@kbeckmann
Last active April 7, 2021 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kbeckmann/2980e9f7371e3ce8cc79a415e0a4248b to your computer and use it in GitHub Desktop.
Save kbeckmann/2980e9f7371e3ce8cc79a415e0a4248b to your computer and use it in GitHub Desktop.
Trying to run cxxrtl with a complex design
from nmigen import *
from nmigen._toolchain.yosys import *
from nmigen.back.cxxrtl import rtlil
import os, subprocess
def _convert_rtlil_text(rtlil_text, black_boxes, verilog_boxes, *, src_loc_at=0):
if black_boxes is not None:
if not isinstance(black_boxes, dict):
raise TypeError("CXXRTL black boxes must be a dictionary, not {!r}"
.format(black_boxes))
for box_name, box_source in black_boxes.items():
if not isinstance(box_name, str):
raise TypeError("CXXRTL black box name must be a string, not {!r}"
.format(box_name))
if not isinstance(box_source, str):
raise TypeError("CXXRTL black box source code must be a string, not {!r}"
.format(box_source))
yosys = find_yosys(lambda ver: ver >= (0, 9, 3468))
script = []
if black_boxes is not None:
for box_name, box_source in black_boxes.items():
script.append("read_ilang <<rtlil\n{}\nrtlil".format(box_source))
# ------- Patch that adds verilog_boxes
if verilog_boxes is not None:
for box_name, box_source in verilog_boxes.items():
script.append(f"read_verilog <<verilog_{box_name}\n{box_source}\nverilog_{box_name}")
# -------
script.append("read_ilang <<rtlil\n{}\nrtlil".format(rtlil_text))
script.append("delete w:$verilog_initial_trigger")
script.append("write_cxxrtl")
return yosys.run(["-q", "-"], "\n".join(script), src_loc_at=1 + src_loc_at, ignore_warnings=True)
def convert(*args, black_boxes=None, verilog_boxes=None, **kwargs):
rtlil_text = rtlil.convert(*args, **kwargs)
return _convert_rtlil_text(rtlil_text, black_boxes, verilog_boxes, src_loc_at=1)
def build_blinky():
m = Module()
foo = Signal(32)
bar = Signal(32)
m.submodules.example = example = Instance("example",
i_clk=ClockSignal(),
i_foo=foo,
o_bar=bar,
)
example_v = """
module example(
input wire clk,
input wire [31:0] foo,
output wire [31:0] bar
);
always @ (posedge clk)
begin
bar <= foo + bar + 42;
end
endmodule
"""
output = convert(m, ports=(foo, bar), verilog_boxes={"example": example_v})
root = os.path.join("build")
if not os.path.exists(root):
os.mkdir("build")
filename = os.path.join(root, "top.cpp")
elfname = os.path.join(root, "top.elf")
with open(filename, "w") as f:
f.write(output)
f.write('''
#include <iostream>
#include <fstream>
#include <backends/cxxrtl/cxxrtl_vcd.h>
int main(int argc, char *argv[])
{
cxxrtl_design::p_top top;
vcd_writer w;
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " out.vcd" << std::endl;
return 1;
}
debug_items items;
top.debug_info(items);
w.add(items);
std::cout << "foo" << " " << "bar" << std::endl;
for (int i=0; i < 16; i++) {
if (i >= 8) {
top.p_foo = value<32>{100u};
}
top.step();
top.p_clk = value<1>{0u};
top.step();
top.p_clk = value<1>{1u};
std::cout << top.p_foo << " " << top.p_bar << std::endl;
w.sample(i);
}
std::cout << "Writing " << argv[1] << std::endl;
std::ofstream outfile (argv[1]);
outfile << w.buffer;
outfile.close();
return 0;
}''')
f.close()
print(subprocess.check_call([
"clang++", "-I", "/usr/share/yosys/include",
"-O3", "-std=c++11", "-o", elfname, filename]))
print(subprocess.check_call([elfname, "build/top.vcd"]))
def build_chacha():
import os
import subprocess
cs = Signal()
we = Signal()
addr = Signal(8)
write_data = Signal(32)
read_data = Signal(32)
m = Module()
m.submodules.chacha_top = chacha_top = Instance("chacha",
i_clk=ClockSignal(),
# i_reset_n=ResetSignal(),
i_reset_n=Const(1),
i_cs=cs,
i_we=we,
i_addr=addr,
i_write_data=write_data,
o_read_data=read_data,
)
# https://github.com/secworks/chacha
output = convert(m, ports=(
cs,
we,
addr,
write_data,
read_data),
verilog_boxes={
"chacha.v": open("chacha.v").read(),
"chacha_core.v": open("chacha_core.v").read(),
"chacha_qr.v": open("chacha_qr.v").read(),
})
root = os.path.join("build")
if not os.path.exists(root):
os.mkdir("build")
print("output -----------")
print(output)
print("------------------")
filename = os.path.join(root, "top.cpp")
elfname = os.path.join(root, "top.elf")
with open(filename, "w") as f:
f.write(output)
f.write('''
#include <iostream>
#include <fstream>
#include <backends/cxxrtl/cxxrtl_vcd.h>
int main(int argc, char *argv[])
{
cxxrtl_design::p_top top;
vcd_writer w;
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " out.vcd" << std::endl;
return 1;
}
debug_items items;
top.debug_info(items);
w.add(items);
top.step();
top.p_clk = value<1>{0u};
top.step();
top.p_clk = value<1>{1u};
top.p_cs = value<1>{1u};
top.p_we = value<1>{1u};
top.p_addr = value<8>{8u};
top.p_data_write = value<32>{1u};
for (int i=0; i < 64; i++) {
top.step();
top.p_clk = value<1>{0u};
top.step();
top.p_clk = value<1>{1u};
w.sample(i);
}
std::cout << "Writing " << argv[1] << std::endl;
std::ofstream outfile (argv[1]);
outfile << w.buffer;
outfile.close();
return 0;
}''')
f.close()
print(subprocess.check_call([
"clang++", "-I", "/usr/share/yosys/include",
"-O3", "-std=c++11", "-o", elfname, filename]))
print(subprocess.check_call([elfname, "build/top.vcd"]))
if __name__ == "__main__":
# Uncoment blinky to try it, it works fine
# build_blinky()
print("""Please download these files before running, then uncomment the last line
wget https://raw.githubusercontent.com/secworks/chacha/master/src/rtl/chacha.v
wget https://raw.githubusercontent.com/secworks/chacha/master/src/rtl/chacha_core.v
wget https://raw.githubusercontent.com/secworks/chacha/master/src/rtl/chacha_qr.v
""")
# build_chacha()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment