add logic analyzer playback module auto-generation

This commit is contained in:
Fischer Moseley 2023-04-15 20:51:44 -04:00
parent 9d8836bda3
commit 7c1e4fc2c0
7 changed files with 190 additions and 88 deletions

View File

@ -12,3 +12,4 @@ with open("capture.pkl", "rb") as f:
m.my_logic_analyzer.export_vcd(capture, "capture.vcd")
m.my_logic_analyzer.export_mem(capture, "capture.mem")
m.my_logic_analyzer.export_playback_module("sim/playback.v")

View File

@ -0,0 +1,57 @@
/*
This playback module was generated with Manta v0.0.0 on 15 Apr 2023 at 20:50:31 by fischerm
If this breaks or if you've got dank formal verification memes, contact fischerm [at] mit.edu
Provided under a GNU GPLv3 license. Go wild.
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
this into your source!
my_logic_analyzer_playback #(.MEM_FILE("capture.mem")) my_logic_analyzer_playback_inst (
.clk(clk),
.enable(1'b1),
.larry(larry),
.curly(curly),
.moe(moe),
.shemp(shemp));
*/
module my_logic_analyzer_playback (
input wire clk,
input wire enable,
output reg done,
output reg larry,
output reg curly,
output reg moe,
output reg [3:0] shemp);
parameter MEM_FILE = "";
localparam SAMPLE_DEPTH = 4096;
localparam TOTAL_PROBE_WIDTH = 7;
reg [TOTAL_PROBE_WIDTH-1:0] capture [SAMPLE_DEPTH-1:0];
reg [$clog2(SAMPLE_DEPTH)-1:0] addr;
reg [TOTAL_PROBE_WIDTH-1:0] sample;
assign done = (addr >= SAMPLE_DEPTH);
initial begin
$display("Loading capture from %s", MEM_FILE);
$readmemb(MEM_FILE, capture, 0, SAMPLE_DEPTH-1);
addr = 0;
end
always @(posedge clk) begin
if (enable && !done) begin
addr = addr + 1;
sample = capture[addr];
{shemp, moe, curly, larry} = sample;
end
end
endmodule

View File

@ -0,0 +1,42 @@
`default_nettype none
`timescale 1ns/1ps
module playback_tb();
logic clk;
always begin
#5;
clk = !clk;
end
logic larry;
logic curly;
logic moe;
logic [3:0] shemp;
my_logic_analyzer_playback #(.MEM_FILE("capture.mem")) my_logic_analyzer_playback_inst (
.clk(clk),
.enable(1'b1),
.larry(larry),
.curly(curly),
.moe(moe),
.shemp(shemp));
initial begin
clk = 0;
$dumpfile("playback_tb.vcd");
$dumpvars(0, playback_tb);
#(4500*5);
$finish();
end
endmodule
`default_nettype wire

View File

@ -1,80 +0,0 @@
`default_nettype none
`timescale 1ns/1ps
module replay_tb();
logic clk;
always begin
#5;
clk = !clk;
end
logic larry;
logic curly;
logic moe;
logic [3:0] shemp;
my_logic_analyzer_playback playback (
.clk(clk),
.enable(1'b1),
.done(),
.larry(larry),
.curly(curly),
.moe(moe),
.shemp(shemp));
initial begin
clk = 0;
$dumpfile("replay_tb.vcd");
$dumpvars(0, replay_tb);
#(4500*5);
$finish();
end
endmodule
module my_logic_analyzer_playback (
input wire clk,
input wire enable,
output reg done,
output reg larry,
output reg curly,
output reg moe,
output reg [3:0] shemp);
localparam FILENAME = "capture.mem";
localparam SAMPLE_DEPTH = 4096;
localparam TOTAL_PROBE_WIDTH = 7;
reg [TOTAL_PROBE_WIDTH-1:0] capture [SAMPLE_DEPTH-1:0];
reg [$clog2(SAMPLE_DEPTH)-1:0] addr;
reg [TOTAL_PROBE_WIDTH-1:0] sample;
assign done = (addr >= SAMPLE_DEPTH);
initial begin
$display("Loading capture from %s", FILENAME);
$readmemb(FILENAME, capture);
addr = 0;
end
always @(posedge clk) begin
if (enable && !done) begin
addr = addr + 1;
sample = capture[addr];
larry = sample[0];
curly = sample[1];
moe = sample[2];
shemp = sample[6:3];
end
end
endmodule
`default_nettype wire

View File

@ -4,7 +4,7 @@ from sys import argv
import os
from datetime import datetime
version = "0.0.0"
version = "v0.0.0"
class VerilogManipulator:
def __init__(self, filepath=None):
@ -685,8 +685,38 @@ class LogicAnalyzerCore:
w = self.total_probe_width
f.writelines([f'{s:0{w}b}\n' for s in capture_data])
def export_mem_loader(self):
pass
def export_playback_module(self, path):
playback = VerilogManipulator("logic_analyzer_playback_tmpl.v")
module_name = f"{self.name}_playback"
playback.sub(module_name, "/* MODULE_NAME */")
playback.sub(version, "/* VERSION */")
timestamp = datetime.now().strftime("%d %b %Y at %H:%M:%S")
playback.sub(timestamp, "/* TIMESTAMP */")
user = os.environ.get("USER", os.environ.get("USERNAME"))
playback.sub(user, "/* USER */")
ports = [f".{name}({name})" for name in self.probes.keys()]
ports = ",\n".join(ports)
playback.sub(ports, "/* PORTS */")
playback.sub(self.sample_depth, "/* SAMPLE_DEPTH */")
playback.sub(self.total_probe_width, "/* TOTAL_PROBE_WIDTH */")
# see the note in generate_logic_analyzer_def about why we do this
probes_concat = list(self.probes.keys())[::-1]
probes_concat = '{' + ', '.join(probes_concat) + '}'
playback.sub(probes_concat, "/* PROBES_CONCAT */")
probe_dec = playback.net_dec(self.probes, "output reg")
playback.sub(probe_dec, "/* PROBE_DEC */")
with open(path, "w") as f:
f.write(playback.get_hdl())
def part_select_capture_data(self, capture_data, probe_name):
@ -1030,6 +1060,8 @@ reg {self.cores[-1].name}_btx_valid;\n"""
def generate_hdl(self, output_filepath):
manta = VerilogManipulator("manta_def_tmpl.v")
manta.sub(version, "/* VERSION */")
timestamp = datetime.now().strftime("%d %b %Y at %H:%M:%S")
manta.sub(timestamp, "/* TIMESTAMP */")

View File

@ -0,0 +1,51 @@
/*
This playback module was generated with Manta /* VERSION */ on /* TIMESTAMP */ by /* USER */
If this breaks or if you've got dank formal verification memes, contact fischerm [at] mit.edu
Provided under a GNU GPLv3 license. Go wild.
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
this into your source!
/* MODULE_NAME */ #(.MEM_FILE("capture.mem")) /* MODULE_NAME */_inst (
.clk(clk),
.enable(1'b1),
/* PORTS */);
*/
module /* MODULE_NAME */ (
input wire clk,
input wire enable,
output reg done,
/* PROBE_DEC */);
parameter MEM_FILE = "";
localparam SAMPLE_DEPTH = /* SAMPLE_DEPTH */;
localparam TOTAL_PROBE_WIDTH = /* TOTAL_PROBE_WIDTH */;
reg [TOTAL_PROBE_WIDTH-1:0] capture [SAMPLE_DEPTH-1:0];
reg [$clog2(SAMPLE_DEPTH)-1:0] addr;
reg [TOTAL_PROBE_WIDTH-1:0] sample;
assign done = (addr >= SAMPLE_DEPTH);
initial begin
$display("Loading capture from %s", MEM_FILE);
$readmemb(MEM_FILE, capture, 0, SAMPLE_DEPTH-1);
addr = 0;
end
always @(posedge clk) begin
if (enable && !done) begin
addr = addr + 1;
sample = capture[addr];
/* PROBES_CONCAT */ = sample;
end
end
endmodule

View File

@ -1,13 +1,12 @@
/*
This manta definition was generated on /* TIMESTAMP */ by /* USER */
This playback module was generated with Manta /* VERSION */ on /* TIMESTAMP */ by /* USER */
If this breaks or if you've got dank formal verification memes,
please contact fischerm [at] mit.edu
If this breaks or if you've got dank formal verification memes, contact fischerm [at] mit.edu
Provided under a GNU GPLv3 license. Go wild.
Here's an example instantiation of the Manta module you configured,
feel free to copy-paste this into your source!
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
this into your source!
manta manta_inst (
.clk(clk),