add logic analyzer playback module auto-generation
This commit is contained in:
parent
9d8836bda3
commit
7c1e4fc2c0
|
|
@ -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_vcd(capture, "capture.vcd")
|
||||||
m.my_logic_analyzer.export_mem(capture, "capture.mem")
|
m.my_logic_analyzer.export_mem(capture, "capture.mem")
|
||||||
|
m.my_logic_analyzer.export_playback_module("sim/playback.v")
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -4,7 +4,7 @@ from sys import argv
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
version = "0.0.0"
|
version = "v0.0.0"
|
||||||
|
|
||||||
class VerilogManipulator:
|
class VerilogManipulator:
|
||||||
def __init__(self, filepath=None):
|
def __init__(self, filepath=None):
|
||||||
|
|
@ -685,8 +685,38 @@ class LogicAnalyzerCore:
|
||||||
w = self.total_probe_width
|
w = self.total_probe_width
|
||||||
f.writelines([f'{s:0{w}b}\n' for s in capture_data])
|
f.writelines([f'{s:0{w}b}\n' for s in capture_data])
|
||||||
|
|
||||||
def export_mem_loader(self):
|
def export_playback_module(self, path):
|
||||||
pass
|
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):
|
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):
|
def generate_hdl(self, output_filepath):
|
||||||
manta = VerilogManipulator("manta_def_tmpl.v")
|
manta = VerilogManipulator("manta_def_tmpl.v")
|
||||||
|
|
||||||
|
manta.sub(version, "/* VERSION */")
|
||||||
|
|
||||||
timestamp = datetime.now().strftime("%d %b %Y at %H:%M:%S")
|
timestamp = datetime.now().strftime("%d %b %Y at %H:%M:%S")
|
||||||
manta.sub(timestamp, "/* TIMESTAMP */")
|
manta.sub(timestamp, "/* TIMESTAMP */")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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,
|
If this breaks or if you've got dank formal verification memes, contact fischerm [at] mit.edu
|
||||||
please contact fischerm [at] mit.edu
|
|
||||||
|
|
||||||
Provided under a GNU GPLv3 license. Go wild.
|
Provided under a GNU GPLv3 license. Go wild.
|
||||||
|
|
||||||
Here's an example instantiation of the Manta module you configured,
|
Here's an example instantiation of the Manta module you configured, feel free to copy-paste
|
||||||
feel free to copy-paste this into your source!
|
this into your source!
|
||||||
|
|
||||||
manta manta_inst (
|
manta manta_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue