From 7c1e4fc2c0718f7adeab30260b309065ece8b660 Mon Sep 17 00:00:00 2001 From: Fischer Moseley <42497969+fischermoseley@users.noreply.github.com> Date: Sat, 15 Apr 2023 20:51:44 -0400 Subject: [PATCH] add logic analyzer playback module auto-generation --- .../logic_analyzer/run_logic_analyzer.py | 1 + .../nexys_a7/logic_analyzer/sim/playback.v | 57 +++++++++++++ .../logic_analyzer/sim/playback_tb.sv | 42 ++++++++++ .../nexys_a7/logic_analyzer/sim/replay_tb.sv | 80 ------------------- src/manta/__init__.py | 38 ++++++++- src/manta/logic_analyzer_playback_tmpl.v | 51 ++++++++++++ src/manta/manta_def_tmpl.v | 9 +-- 7 files changed, 190 insertions(+), 88 deletions(-) create mode 100644 examples/nexys_a7/logic_analyzer/sim/playback.v create mode 100644 examples/nexys_a7/logic_analyzer/sim/playback_tb.sv delete mode 100644 examples/nexys_a7/logic_analyzer/sim/replay_tb.sv create mode 100644 src/manta/logic_analyzer_playback_tmpl.v diff --git a/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py b/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py index d6577a0..c9f274d 100644 --- a/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py +++ b/examples/nexys_a7/logic_analyzer/run_logic_analyzer.py @@ -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") \ No newline at end of file diff --git a/examples/nexys_a7/logic_analyzer/sim/playback.v b/examples/nexys_a7/logic_analyzer/sim/playback.v new file mode 100644 index 0000000..99aaa46 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/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 \ No newline at end of file diff --git a/examples/nexys_a7/logic_analyzer/sim/playback_tb.sv b/examples/nexys_a7/logic_analyzer/sim/playback_tb.sv new file mode 100644 index 0000000..b3487a6 --- /dev/null +++ b/examples/nexys_a7/logic_analyzer/sim/playback_tb.sv @@ -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 \ No newline at end of file diff --git a/examples/nexys_a7/logic_analyzer/sim/replay_tb.sv b/examples/nexys_a7/logic_analyzer/sim/replay_tb.sv deleted file mode 100644 index 9448715..0000000 --- a/examples/nexys_a7/logic_analyzer/sim/replay_tb.sv +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/manta/__init__.py b/src/manta/__init__.py index 601f573..334770c 100644 --- a/src/manta/__init__.py +++ b/src/manta/__init__.py @@ -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 */") diff --git a/src/manta/logic_analyzer_playback_tmpl.v b/src/manta/logic_analyzer_playback_tmpl.v new file mode 100644 index 0000000..3088091 --- /dev/null +++ b/src/manta/logic_analyzer_playback_tmpl.v @@ -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 \ No newline at end of file diff --git a/src/manta/manta_def_tmpl.v b/src/manta/manta_def_tmpl.v index 40db13c..8d3ec90 100644 --- a/src/manta/manta_def_tmpl.v +++ b/src/manta/manta_def_tmpl.v @@ -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),