M compress.py => compress.py +0 -9
@@ 433,14 433,5 @@ if __name__ == '__main__':
for i, l in enumerate(test_lines):
print('{:02d} {:080x}'.format(i, l))
run_simulation(dut, [lines_in(dut, test_lines), lines_out(dut, test_lines)], vcd_name='out.vcd')
- elif sys.argv[1] == 'verilator':
- import utils
- from migen.fhdl.verilog import convert
- tb = CompressFrames(160, 144, 1024)
- c = convert(tb, ios={
- tb.input.data, tb.input.ready, tb.input.valid,
- tb.output.data, tb.output.ready, tb.output.valid})
- utils.update_verilog_if_changed('compress_tb.v', c)
- utils.verilate(['compress_tb.v', 'compress_tb_wrap.cpp'], output='compress_tb')
else:
raise ValueError(sys.argv[1])
D compress_tb_wrap.cpp => compress_tb_wrap.cpp +0 -92
@@ 1,92 0,0 @@
-#include "Vcompress_tb.h"
-#include "verilated.h"
-#include "verilated_vcd_c.h"
-#include "tb_wrap_utils.h"
-
-#include <stdio.h>
-
-int main(int argc, char **argv)
-{
- Verilated::commandArgs(argc, argv);
- Vcompress_tb* top = new Vcompress_tb;
-
- Verilated::traceEverOn(true);
- VerilatedVcdC* trace = new VerilatedVcdC;
- top->trace(trace, 99);
-
- trace->open("compress_tb.vcd");
-
- top->sys_rst = 1;
- for(unsigned i = 0; i != 10; i += 1) {
- top->sys_clk = i & 1;
- top->eval();
- }
- top->sys_rst = 0;
-
- top->output_ready = 1;
- uint32_t last_line = UINT32_MAX;
- uint32_t last_out = 0;
- uint32_t sys_clk = 0;
- bool no_more_lines = false;
- while(!Verilated::gotFinish()) {
- /* GB LCD runs at ~4.19MHz, each scanline takes 456 cycles. FPGA clock
- * is 25MHz, so divide by 6 to get 4MHz.
- */
- uint32_t line_idx = sys_clk / (6 * 456);
- /* GB LCD frame is 144 lines high, with 10 lines worth of vblank at the
- * end of each frame.
- */
- uint32_t line_in_frame = line_idx % 154;
-
- if(!no_more_lines && line_idx != last_line) {
- last_line = line_idx;
- fprintf(stderr, "input: line %d %d (%u)\n", line_idx, line_in_frame, sys_clk);
- if(line_in_frame < 144) {
- if(!read_line(top->input_data)) {
- no_more_lines = true;
- fprintf(stderr, "**EOF\n");
- }
- else {
- if(!top->input_ready) {
- fprintf(stderr, "Overflow\n");
- std::exit(1);
- }
- top->input_valid = 1;
- }
- }
- }
-
- /* output UART is running at 2MBaud, 9 bits per output byte
- * = sys_clk / 12.5 / 9 */
- uint32_t uart_byte = sys_clk / 113;
-
- if(last_out != uart_byte) {
- top->output_ready = 1;
- }
-
- /* Falling edge */
- top->sys_clk = 0;
- top->eval();
- trace->dump(sys_clk << 1);
- /* Rising edge */
- top->sys_clk = 1;
- top->eval();
- trace->dump((sys_clk << 1) + 1);
-
- if(top->input_valid && top->input_ready) {
- top->input_valid = 0;
- }
-
- if(top->output_valid && top->output_ready) {
- printf("%02x\n", top->output_data);
- fflush(stdout);
- last_out = uart_byte;
- top->output_ready = 0;
- }
- sys_clk += 1;
- }
-
- trace->close();
-
- delete top;
-}
M dump_pgm.py => dump_pgm.py +7 -1
@@ 1,10 1,12 @@
#!/usr/bin/env python3
+import sys
import compress_ref
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Dump image(s) as a newline separated stream of packed lines (hex encoded)')
+ parser.add_argument('--text', '-t', help='Dump as newline separated hex-encoded lines rather than raw binary')
parser.add_argument('pgms', nargs='+', help='Images to dump')
args = parser.parse_args()
@@ 12,4 14,8 @@ if __name__ == '__main__':
for filename in args.pgms:
with open(filename) as f:
for lv in compress_ref.pixels_to_lines(compress_ref.read_pgm(f), 160):
- print('{:080X}'.format(lv))
+ if args.text:
+ print('{:080X}'.format(lv))
+ else:
+ sys.stdout.buffer.write(lv.to_bytes(40, byteorder='little'))
+ sys.stdout.buffer.flush()
M gbcap.py => gbcap.py +24 -3
@@ 286,8 286,29 @@ if __name__ == '__main__':
run_simulation(dut, [tx(dut), rx(dut), check_comp_out(dut)], vcd_name='out.vcd')
elif sys.argv[1] == 'verilator':
- import utils
+ import subprocess
+ import shutil
+ import os
from migen.fhdl.verilog import convert
+
+ def update_verilog_if_changed(path, cvt):
+ assert not cvt.data_files
+ current = None
+ if os.path.exists(path):
+ with open(path, 'r') as f:
+ current = f.read()
+ if current != cvt.main_source:
+ with open(path, 'w') as f:
+ f.write(cvt.main_source)
+
+ def verilate(files, output=None):
+ cmd = ['verilator', '-Wno-COMBDLY', '-Wno-fatal', '-cc', '-CFLAGS', '-ggdb', '--trace', '--exe', '--build']
+ if output is not None:
+ cmd += ['-o', output]
+ cmd += files
+ res = subprocess.run(cmd)
+ res.check_returncode()
+
class TB(Module):
def __init__(self):
self.serial_pads = Record([('tx', 1), ('rx', 1)])
@@ 311,5 332,5 @@ if __name__ == '__main__':
tb.compress.error,
}
c = convert(tb, ios=ios)
- utils.update_verilog_if_changed('gbcap_tb.v', c)
- utils.verilate(['gbcap_tb.v', 'gbcap_tb_wrap.cpp'], output='gbcap_tb')
+ update_verilog_if_changed('gbcap_tb.v', c)
+ verilate(['gbcap_tb.v', 'gbcap_tb_wrap.cpp'], output='gbcap_tb')
M gbcap_tb_wrap.cpp => gbcap_tb_wrap.cpp +23 -3
@@ 1,10 1,25 @@
#include "Vgbcap_tb.h"
#include "verilated.h"
#include "verilated_vcd_c.h"
-#include "tb_wrap_utils.h"
#include <stdio.h>
+static bool read_line(FILE* f, uint32_t* buf)
+{
+ uint8_t bytes[40];
+ size_t n = fread(bytes, 1, 40, f);
+ if(n != 40) {
+ return false;
+ }
+ for(unsigned w = 0; w != 10; w += 1) {
+ buf[w] = 0;
+ for(unsigned b = 0; b != 4; b += 1) {
+ buf[w] |= bytes[(4*w) + b] << (8 * b);
+ }
+ }
+ return true;
+}
+
int main(int argc, char **argv)
{
Verilated::commandArgs(argc, argv);
@@ 43,7 58,7 @@ int main(int argc, char **argv)
last_line = line_idx;
fprintf(stderr, "input: line %d %d (%u)\n", line_idx, line_in_frame, sys_clk);
if(line_in_frame < 144) {
- if(!read_line(top->line_pads_data)) {
+ if(!read_line(stdin, top->line_pads_data)) {
no_more_lines = true;
fprintf(stderr, "**EOF\n");
}
@@ 67,8 82,13 @@ int main(int argc, char **argv)
}
if(top->valid_1) {
- printf("%02x\n", top->data_1);
+ fwrite(&top->data_1, 1, 1, stdout);
fflush(stdout);
+ if(no_more_lines) {
+ /* Make it clear something is still happening */
+ fprintf(stderr, ".");
+ fflush(stderr);
+ }
}
if(top->valid) {
D tb_wrap_utils.h => tb_wrap_utils.h +0 -52
@@ 1,52 0,0 @@
-#include <stdio.h>
-#include <assert.h>
-
-static inline unsigned fromhex(char const s[2])
-{
- unsigned accum = 0;
- for(unsigned i = 0; i != 2; i += 1) {
- unsigned n = 0;
- if(s[i] >= '0' && s[i] <= '9') {
- n = s[i] - '0';
- }
- else if(s[i] >= 'a' && s[i] <= 'z') {
- n = s[i] - 'a' + 10;
- }
- else if(s[i] >= 'A' && s[i] <= 'Z') {
- n = s[i] - 'A' + 10;
- }
- else {
- assert(false);
- }
- accum += n << ((1 - i) * 4);
- }
- return accum;
-}
-
-static inline bool read_line(uint32_t* line)
-{
- char hex[2];
- for(unsigned i = 0; i != 10; i += 1) {
- uint32_t word = 0;
- for(unsigned w = 0; w != 4; w += 1) {
- if(fread(hex, 1, 2, stdin) != 2) {
- return false;
- }
- unsigned v = fromhex(hex);
- word |= v << ((3 - w) * 8);
- }
- line[9 - i] = word;
- }
- /* Allow last line to omit \n */
- if(fread(hex, 1, 1, stdin) == 1 && hex[0] != '\n') {
- return false;
- }
-
- return true;
-}
-
-static unsigned get_pixel(uint32_t const* line, unsigned idx)
-{
- assert(idx < 160);
- return (line[idx / 16] >> ((idx % 16) * 2)) & 3u;
-}
D utils.py => utils.py +0 -21
@@ 1,21 0,0 @@
-import subprocess
-import shutil
-import os
-
-def update_verilog_if_changed(path, cvt):
- assert not cvt.data_files
- current = None
- if os.path.exists(path):
- with open(path, 'r') as f:
- current = f.read()
- if current != cvt.main_source:
- with open(path, 'w') as f:
- f.write(cvt.main_source)
-
-def verilate(files, output=None):
- cmd = ['verilator', '-Wno-COMBDLY', '-Wno-fatal', '-cc', '-CFLAGS', '-ggdb', '--trace', '--exe', '--build']
- if output is not None:
- cmd += ['-o', output]
- cmd += files
- res = subprocess.run(cmd)
- res.check_returncode()