raster simulate

This commit is contained in:
Peter McGoron 2022-12-23 20:22:48 +00:00
parent 013774e28b
commit 96e9a3d043
5 changed files with 292 additions and 144 deletions

View File

@ -3,7 +3,7 @@
.PHONY: test clean .PHONY: test clean
test: obj_dir/Vram_fifo obj_dir/Vram_shim test: obj_dir/Vram_fifo obj_dir/Vram_shim obj_dir/Vraster_sim
RAM_FIFO_SRC= ram_fifo.v ram_fifo_dual_port.v ram_fifo_sim.cpp RAM_FIFO_SRC= ram_fifo.v ram_fifo_dual_port.v ram_fifo_sim.cpp
obj_dir/Vram_fifo.mk: ${RAM_FIFO_SRC} obj_dir/Vram_fifo.mk: ${RAM_FIFO_SRC}
@ -11,7 +11,7 @@ obj_dir/Vram_fifo.mk: ${RAM_FIFO_SRC}
${RAM_FIFO_SRC} ${RAM_FIFO_SRC}
obj_dir/Vram_fifo: obj_dir/Vram_fifo.mk obj_dir/Vram_fifo: obj_dir/Vram_fifo.mk
cd obj_dir && make -f Vram_fifo.mk cd obj_dir && make -f Vram_fifo.mk
@./obj_dir/Vram_fifo && echo 'Vram_fifo successful' @./obj_dir/Vram_fifo && echo 'ram_fifo successful'
RAM_SHIM_SRC= ram_shim.v ram_fifo.v ram_fifo_dual_port.v ram_shim_sim.cpp RAM_SHIM_SRC= ram_shim.v ram_fifo.v ram_fifo_dual_port.v ram_shim_sim.cpp
obj_dir/Vram_shim.mk: ${RAM_SHIM_SRC} ram_shim_cmds.vh ram_shim_cmds.h obj_dir/Vram_shim.mk: ${RAM_SHIM_SRC} ram_shim_cmds.vh ram_shim_cmds.h
@ -20,14 +20,26 @@ obj_dir/Vram_shim.mk: ${RAM_SHIM_SRC} ram_shim_cmds.vh ram_shim_cmds.h
${RAM_SHIM_SRC} ${RAM_SHIM_SRC}
obj_dir/Vram_shim: obj_dir/Vram_shim.mk ram_shim_sim.cpp obj_dir/Vram_shim: obj_dir/Vram_shim.mk ram_shim_sim.cpp
cd obj_dir && make -f Vram_shim.mk cd obj_dir && make -f Vram_shim.mk
@./obj_dir/Vram_shim && echo 'Vram_shim successful' @./obj_dir/Vram_shim && echo 'ram_shim successful'
RASTER_SIM_SRC = raster_sim.v raster.v ram_shim.v ram_fifo.v ram_fifo_dual_port.v raster_sim.cpp
obj_dir/Vraster_sim.mk: ${RASTER_SIM_SRC} raster_cmds.vh raster_cmds.h ram_shim_cmds.vh ram_shim_cmds.h
verilator --cc --exe -Wall --trace --trace-fst -CFLAGS -Wall \
${RASTER_SIM_SRC}
obj_dir/Vraster_sim: obj_dir/Vraster_sim.mk raster_sim.cpp
cd obj_dir && make -f Vraster_sim.mk
@./obj_dir/Vraster_sim && echo 'raster successful'
####### Codegen ######## ####### Codegen ########
ram_shim_cmds.h: ram_shim_cmds.vh ram_shim_cmds.h: ram_shim_cmds.vh
echo '#pragma once' > ram_shim_cmds.h echo '#pragma once' > ram_shim_cmds.h
sed 's/`define/#define/g; s/`//g' ram_shim_cmds.vh >> ram_shim_cmds.h sed 's/`define/#define/g; s/`//g' ram_shim_cmds.vh >> ram_shim_cmds.h
raster_cmds.h: raster_cmds.vh
echo '#pragma once' > raster_cmds.h
sed 's/`define/#define/g; s/`//g' raster_cmds.vh >> raster_cmds.h
clean: clean:
rm -rf obj_dir rm -rf obj_dir
rm *.vcd ram_shim_cmds.h rm -f *.vcd ram_shim_cmds.h

View File

@ -8,50 +8,50 @@
`include "raster_cmds.vh" `include "raster_cmds.vh"
`timescale 10ns/10ns `timescale 10ns/10ns
module raster #( module raster #(
parameter SAMPLEWID = 9, parameter DAC_WAIT_BETWEEN_CMD = 10
parameter DAC_DATA_WID = 20,
parameter DAC_WID = 24,
parameter DAC_WAIT_BETWEEN_CMD = 10,
parameter TIMER_WID = 4,
parameter STEPWID = 16,
parameter ADCNUM = 9,
parameter MAX_ADC_DATA_WID = 24
) ( ) (
input clk, input clk,
`ifdef VERILATOR
output is_running,
`endif
/* Kernel interface. */ /* Kernel interface. */
input [`RASTER_CMD_WID-1:0] kernel_cmd, input [`RASTER_CMD_WID-1:0] kernel_cmd,
/* verilator lint_off UNUSEDSIGNAL */
input [`RASTER_DATA_WID-1:0] kernel_data_in, input [`RASTER_DATA_WID-1:0] kernel_data_in,
/* verilator lint_on UNUSEDSIGNAL */
output reg [`RASTER_DATA_WID-1:0] kernel_data_out, output reg [`RASTER_DATA_WID-1:0] kernel_data_out,
input kernel_ready, input kernel_ready,
output reg kernel_finished, output reg kernel_finished,
/* X and Y DAC piezos */ /* X and Y DAC piezos */
output x_arm, output x_arm,
output [DAC_WID-1:0] x_to_dac, output [`DAC_WID-1:0] x_to_dac,
/* verilator lint_off UNUSED */ /* verilator lint_off UNUSED */
input [DAC_WID-1:0] x_from_dac, input [`DAC_WID-1:0] x_from_dac,
/* verilator lint_on UNUSED */
input x_finished, input x_finished,
output y_arm, output y_arm,
output [DAC_WID-1:0] y_to_dac, output [`DAC_WID-1:0] y_to_dac,
/* verilator lint_off UNUSED */ /* verilator lint_off UNUSED */
input [DAC_WID-1:0] y_from_dac, input [`DAC_WID-1:0] y_from_dac,
/* verilator lint_on UNUSED */
input y_finished, input y_finished,
/* Connections to all possible ADCs. These are connected to SPI masters /* Connections to all possible ADCs. These are connected to SPI masters
* and they will automatically extend ADC value lengths to their highest * and they will automatically extend ADC value lengths to their highest
* values. */ * values. */
output reg [ADCNUM-1:0] adc_arm, output reg [`ADCNUM-1:0] adc_arm,
/* Yosys does not support input arrays. */ /* Yosys does not support input arrays. */
input [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data, input [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data,
input [ADCNUM-1:0] adc_finished, input [`ADCNUM-1:0] adc_finished,
/* RAM DMA. This is generally not directly connected to the /* RAM DMA. This is generally not directly connected to the
* DMA IP. A shim is used in order to write multiple words * DMA IP. A shim is used in order to write multiple words
* to memory. */ * to memory. */
output reg [MAX_ADC_DATA_WID-1:0] data, output reg [`MAX_ADC_DATA_WID-1:0] data,
output reg mem_commit, output reg mem_commit,
input mem_finished input mem_finished
); );
@ -101,43 +101,45 @@ module raster #(
*/ */
localparam WAIT_ON_ARM = 0; localparam WAIT_ON_ARM = 0;
localparam GET_DAC_VALUES = 1; localparam REQUEST_DAC_VALUES = 1;
localparam REQUEST_DAC_VALUES = 2; localparam GET_DAC_VALUES = 2;
localparam MEASURE = 3; localparam WAIT_ADVANCE = 3;
localparam SCAN_ADC_VALUES = 4; localparam MEASURE = 4;
localparam ADVANCE_DAC_WRITE = 5; localparam SCAN_ADC_VALUES = 5;
localparam WAIT_ADVANCE = 6; localparam ADVANCE_DAC_WRITE = 6;
localparam NEXT_LINE = 7; localparam NEXT_LINE = 7;
localparam WAIT_ON_ARM_DEASSERT = 8; localparam WAIT_ON_ARM_DEASSERT = 8;
localparam STATE_WID = 4; localparam STATE_WID = 4;
/********** Loop State ***********/ /********** Loop State ***********/
reg [STATE_WID-1:0] state = WAIT_ON_ARM; reg [STATE_WID-1:0] state = WAIT_ON_ARM;
reg [SAMPLEWID-1:0] sample = 0; reg [`SAMPLEWID-1:0] sample = 0;
reg [SAMPLEWID-1:0] line = 0; reg [`SAMPLEWID-1:0] line = 0;
reg [TIMER_WID-1:0] counter = 0; reg [`TIMERWID-1:0] counter = 0;
reg signed [DAC_DATA_WID-1:0] x_val = 0; reg signed [`DAC_DATA_WID-1:0] x_val = 0;
reg signed [DAC_DATA_WID-1:0] y_val = 0; reg signed [`DAC_DATA_WID-1:0] y_val = 0;
/* Buffer to store all measured ADC values. This /* Buffer to store all measured ADC values. This
* is shifted until it is all zeros to determine * is shifted until it is all zeros to determine
* which ADC values should be read off. * which ADC values should be read off.
*/ */
reg [ADCNUM-1:0] adc_used_tmp = 0; reg [`ADCNUM-1:0] adc_used_tmp = 0;
reg [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data_tmp = 0; reg [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data_tmp = 0;
/********** Loop Parameters *************/ /********** Loop Parameters *************/
reg [ADCNUM-1:0] adc_used = 0; reg [`ADCNUM-1:0] adc_used = 0;
reg is_reverse = 0; reg is_reverse = 0;
reg arm = 0; reg arm = 0;
reg running = 0; reg running = 0;
reg signed [DAC_DATA_WID-1:0] dx = 0; `ifdef VERILATOR
reg signed [DAC_DATA_WID-1:0] dy = 0; assign is_running = running;
reg [TIMER_WID-1:0] settle_time = 0; `endif
reg signed [`DAC_DATA_WID-1:0] dx = 0;
reg signed [`DAC_DATA_WID-1:0] dy = 0;
reg [`TIMERWID-1:0] settle_time = 0;
reg [SAMPLEWID-1:0] max_samples = 0; reg [`SAMPLEWID-1:0] max_samples = 0;
reg [SAMPLEWID-1:0] max_lines = 0; reg [`SAMPLEWID-1:0] max_lines = 0;
reg [STEPWID-1:0] steps_per_sample = 0;
/********** Control Interface ************ /********** Control Interface ************
* This code assumes that RASTER_DATA_WID is greater than all registers. * This code assumes that RASTER_DATA_WID is greater than all registers.
@ -161,25 +163,26 @@ end
// Generates code to handle write requests from the kernel. // Generates code to handle write requests from the kernel.
`define generate_register(code, width, register) \ `define generate_register(code, width, register) \
`generate_register_read(code, width, register) \ `generate_register_read(code, width, register) \
code | `RASTER_WRITE_BIT: begin \ code | `RASTER_WRITE_BIT: \
if (!running && (code) != `RASTER_ARM) begin \ if (!running || (code) == `RASTER_ARM) begin \
register <= kernel_data_in[(width)-1:0]; \ register <= kernel_data_in[(width)-1:0]; \
kernel_finished <= 1; \ kernel_finished <= 1; \
end \
end end
always @ (posedge clk) begin always @ (posedge clk) begin
if (!kernel_ready) kernel_finished <= 0; if (!kernel_ready) kernel_finished <= 0;
else if (kernel_ready) begin case (kernel_cmd) else if (kernel_ready) begin case (kernel_cmd)
`generate_register(`RASTER_MAX_SAMPLES, SAMPLEWID, max_samples) `generate_register(`RASTER_MAX_SAMPLES, `SAMPLEWID, max_samples)
`generate_register(`RASTER_MAX_LINES, SAMPLEWID, max_lines) `generate_register(`RASTER_MAX_LINES, `SAMPLEWID, max_lines)
`generate_register(`RASTER_SETTLE_TIME, TIMER_WID, settle_time) `generate_register(`RASTER_SETTLE_TIME, `TIMERWID, settle_time)
`generate_register(`RASTER_DX, DAC_DATA_WID, dx) `generate_register(`RASTER_DX, `DAC_DATA_WID, dx)
`generate_register(`RASTER_DY, DAC_DATA_WID, dy) `generate_register(`RASTER_DY, `DAC_DATA_WID, dy)
`generate_register(`RASTER_USED_ADCS, ADCNUM, adc_used) `generate_register(`RASTER_USED_ADCS, `ADCNUM, adc_used)
`generate_register(`RASTER_STEPS_PER_SAMPLE, STEPWID, steps_per_sample)
`generate_register(`RASTER_ARM, 1, arm) `generate_register(`RASTER_ARM, 1, arm)
`generate_register_read(`RASTER_RUNNING, 1, running) `generate_register_read(`RASTER_RUNNING, 1, running)
`ifdef VERILATOR
default: $error("unknown kernel message");
`endif
endcase end endcase end
end end
`undef generate_register_read `undef generate_register_read
@ -234,8 +237,8 @@ always @ (posedge clk) begin
x_arm <= 1; x_arm <= 1;
y_arm <= 1; y_arm <= 1;
end else if (x_finished && y_finished) begin end else if (x_finished && y_finished) begin
x_val <= x_from_dac[DAC_DATA_WID-1:0]; x_val <= x_from_dac[`DAC_DATA_WID-1:0];
y_val <= y_from_dac[DAC_DATA_WID-1:0]; y_val <= y_from_dac[`DAC_DATA_WID-1:0];
x_arm <= 0; x_arm <= 0;
y_arm <= 0; y_arm <= 0;
@ -262,7 +265,7 @@ always @ (posedge clk) begin
end end
SCAN_ADC_VALUES: if (adc_used_tmp == 0 && !mem_commit) begin SCAN_ADC_VALUES: if (adc_used_tmp == 0 && !mem_commit) begin
`CHECK_DAC_ARM `CHECK_DAC_ARM
if (sample == max_samples) begin if (sample == max_samples-1) begin
dx <= ~dx + 1; dx <= ~dx + 1;
dy <= ~dy + 1; dy <= ~dy + 1;
@ -275,6 +278,7 @@ always @ (posedge clk) begin
is_reverse <= !is_reverse; is_reverse <= !is_reverse;
sample <= 0; sample <= 0;
end else begin end else begin
sample <= sample + 1;
state <= ADVANCE_DAC_WRITE; state <= ADVANCE_DAC_WRITE;
end end
end else if (mem_finished) begin end else if (mem_finished) begin
@ -284,9 +288,9 @@ always @ (posedge clk) begin
end else begin end else begin
`CHECK_DAC_ARM `CHECK_DAC_ARM
adc_used_tmp <= adc_used_tmp << 1; adc_used_tmp <= adc_used_tmp << 1;
adc_data_tmp <= adc_data_tmp << MAX_ADC_DATA_WID; adc_data_tmp <= adc_data_tmp << `MAX_ADC_DATA_WID;
if (adc_used_tmp[ADCNUM-1]) begin if (adc_used_tmp[`ADCNUM-1]) begin
data <= adc_data_tmp[ADCNUM*MAX_ADC_DATA_WID-1:(ADCNUM-1)*MAX_ADC_DATA_WID]; data <= adc_data_tmp[`ADCNUM*`MAX_ADC_DATA_WID-1:(`ADCNUM-1)*`MAX_ADC_DATA_WID];
mem_commit <= 1; mem_commit <= 1;
end end
end end
@ -298,7 +302,6 @@ always @ (posedge clk) begin
y_to_dac <= {4'b0001, y_val + dy}; y_to_dac <= {4'b0001, y_val + dy};
x_arm <= 1; x_arm <= 1;
y_arm <= 1; y_arm <= 1;
sample <= sample + 1;
end else if (x_finished && y_finished) begin end else if (x_finished && y_finished) begin
counter <= 0; counter <= 0;
state <= WAIT_ADVANCE; state <= WAIT_ADVANCE;
@ -306,10 +309,10 @@ always @ (posedge clk) begin
y_arm <= 0; y_arm <= 0;
end end
NEXT_LINE: if (!x_arm || !y_arm) begin NEXT_LINE: if (!x_arm || !y_arm) begin
if (line == max_lines) begin if (line == max_lines-1) begin
state <= WAIT_ON_ARM_DEASSERT; state <= WAIT_ON_ARM_DEASSERT;
running <= 0;
end else begin end else begin
sample <= 0;
/* rotation of (dx,dy) by 90° -> (dy, -dx) */ /* rotation of (dx,dy) by 90° -> (dy, -dx) */
x_val <= x_val + dy; x_val <= x_val + dy;
x_to_dac <= {4'b0001, x_val + dy}; x_to_dac <= {4'b0001, x_val + dy};
@ -327,6 +330,8 @@ always @ (posedge clk) begin
end end
WAIT_ON_ARM_DEASSERT: if (!arm) begin WAIT_ON_ARM_DEASSERT: if (!arm) begin
state <= WAIT_ON_ARM; state <= WAIT_ON_ARM;
end else begin
running <= 0;
end end
endcase endcase
end end

View File

@ -1,6 +1,3 @@
/* Make sure there are no gaps! The code generator will not work
* correctly.
*/
`define RASTER_NOOP 0 `define RASTER_NOOP 0
`define RASTER_MAX_SAMPLES 1 `define RASTER_MAX_SAMPLES 1
`define RASTER_MAX_LINES 2 `define RASTER_MAX_LINES 2
@ -9,11 +6,20 @@
`define RASTER_DY 5 `define RASTER_DY 5
`define RASTER_ARM 6 `define RASTER_ARM 6
`define RASTER_USED_ADCS 7 `define RASTER_USED_ADCS 7
`define RASTER_STEPS_PER_SAMPLE 8 `define RASTER_RUNNING 8
`define RASTER_RUNNING 9
`define RASTER_WRITE_BIT (1 << (`RASTER_CMD_WID - 1)) `define RASTER_WRITE_BIT (1 << (`RASTER_CMD_WID - 1))
`define RASTER_CMD_WID 8 `define RASTER_CMD_WID 8
`define RASTER_DATA_WID 32 `define RASTER_DATA_WID 32
/* Instead of using parameters, these values are preprocessor
* defines so that they may be reference in kernel code.
*/
`define SAMPLEWID 16
`define DAC_DATA_WID 20
`define DAC_WID 24
`define TIMERWID 8
`define ADCNUM 9
`define MAX_ADC_DATA_WID 24

View File

@ -1,25 +1,57 @@
#include <memory>
#include <limits> #include <limits>
#include <cstdint> #include <cstdint>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <cstdarg>
#include <iostream> #include <iostream>
#include <random>
#include <unistd.h> #include <unistd.h>
#include <verilated.h> #include <verilated.h>
#include "ram_shim_cmds.h"
#include "raster_cmds.h"
#include "Vraster_sim.h" #include "Vraster_sim.h"
using ModType = Vraster_sim; using ModType = Vraster_sim;
ModType *mod; ModType *mod;
uint32_t main_time = 0; uint32_t main_time = 0;
double sc_time_stamp() {
return main_time;
}
static void _assert(const char *file, int line, const char *exp, bool ev, const char *fmt, ...) {
if (!ev) {
va_list va;
va_start(va, fmt);
fprintf(stderr, "%s:%d: assertion failed: %s\n", file, line, exp);
vfprintf(stderr, fmt, va);
fprintf(stderr, "\n");
va_end(va);
exit(1);
}
}
#define STRINGIFY(s) #s
/* ,##__VA_ARGS__ is a GNU C extension */
#define my_assert(e, fmt, ...) _assert(__FILE__, __LINE__, STRINGIFY(e), (e), fmt ,##__VA_ARGS__)
static void run_clock() { static void run_clock() {
#ifdef BAILOUT
static int iters = 0;
#endif
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
mod->clk = !mod->clk; mod->clk = !mod->clk;
mod->eval(); mod->eval();
main_time++; main_time++;
#ifdef BAILOUT
iters++;
#endif
} }
#ifdef BAILOUT
if (iters >= 1000000)
exit(2);
#endif
} }
static void cleanup_exit() { static void cleanup_exit() {
@ -33,76 +65,171 @@ static void init(int argc, char **argv) {
mod = new ModType; mod = new ModType;
mod->clk = 0; mod->clk = 0;
atexit(cleanup_exit); atexit(cleanup_exit);
char *seed = getenv("RANDOM_SEED");
if (seed) {
unsigned long i = strtoul(seed, NULL, 10);
srand((unsigned int)i);
}
} }
using V = uint32_t;
// Verilator makes all ports unsigned, even when marked as signed in
// Verilog.
V sign_extend(V x, unsigned len, bool is_signed) {
if (!is_signed)
return x;
// if high bit is 1
if (x >> (len - 1) & 1) {
// This mask selects all bits below the highest bit.
// By inverting it, it selects the highest bit, and all
// higher bits that must be sign extended.
V mask = (1 << len) - 1;
// Set all high bits to 1. The mask has all bits lower
// than the highest bit 0, so the bits in "x" pass through.
return ~mask | x;
} else {
return x;
}
}
static int32_t read_raster_reg(int reg, unsigned siz, bool is_signed) {
mod->kernel_cmd = reg;
mod->kernel_ready = 1;
while (!mod->kernel_finished)
run_clock();
mod->kernel_ready = 0;
run_clock();
return sign_extend(mod->kernel_data_out, siz, is_signed);
}
static int32_t write_raster_reg(int reg, unsigned siz, int32_t val, bool is_signed) {
int32_t oldval = read_raster_reg(reg, siz, is_signed);
mod->kernel_cmd = reg | RASTER_WRITE_BIT;
mod->kernel_data_in = val;
mod->kernel_ready = 1;
while (!mod->kernel_finished)
run_clock();
mod->kernel_ready = 0;
run_clock();
int32_t cval = read_raster_reg(reg, siz, is_signed);
my_assert(cval == val, "written value (%x) != read val (%x)\n", val, cval);
return oldval;
}
static void write_shim_cmd(unsigned cmd, uint32_t val) {
mod->shim_cmd = cmd;
mod->shim_cmd_data = val;
mod->shim_cmd_active = 1;
while (!mod->shim_cmd_finished)
run_clock();
mod->shim_cmd_active = 0;
run_clock();
}
static void read_shim_ptr() {
mod->shim_cmd = RAM_SHIM_READ_PTR;
mod->shim_cmd_active = 1;
while (!mod->shim_cmd_finished)
run_clock();
mod->shim_cmd_active = 0;
run_clock();
}
#define SAMPLES_PER_LINE 16
#define NUM_OF_LINES 16
static size_t expected_store_index = 0;
static void init_values() { static void init_values() {
mod->arm = 0;
mod->max_samples_in = 512;
mod->max_lines_in = 512;
/* Settle time is 1 μs */
mod->settle_time_in = 100;
mod->dx_in = 17;
mod->dy_in = 13;
mod->coord_dac[0] = 0;
mod->coord_dac[1] = 0;
for (int i = 0; i < ADCNUM; i++) for (int i = 0; i < ADCNUM; i++)
mod->adc_data[i] = 0; mod->adc_data[i] = 0;
mod->adc_finished = 0; mod->adc_finished = 0;
mod->adc_used_in = 0;
mod->ram_valid = 0; mod->ram_valid = 0;
my_assert(write_raster_reg(RASTER_MAX_SAMPLES, SAMPLEWID, SAMPLES_PER_LINE, false) == 0, "samples per line was not zero");
my_assert(write_raster_reg(RASTER_MAX_LINES, SAMPLEWID, NUM_OF_LINES, false) == 0, "max lines was not zero");
my_assert(write_raster_reg(RASTER_SETTLE_TIME, TIMERWID, 30, false) == 0, "settle time was not zero");
my_assert(write_raster_reg(RASTER_DX, DAC_DATA_WID, 12, true) == 0, "dx was not zero");
my_assert(write_raster_reg(RASTER_DY, DAC_DATA_WID, 12, true) == 0, "dy was not zero");
my_assert(write_raster_reg(RASTER_USED_ADCS, ADCNUM, 0b111101011, false) == 0, "adcnum was not zero");
expected_store_index = SAMPLES_PER_LINE * NUM_OF_LINES * 7 * 2;
write_shim_cmd(RAM_SHIM_WRITE_LOC, 0x10000);
write_shim_cmd(RAM_SHIM_WRITE_LEN, 0x0FFFF);
} }
uint32_t *measured_values[ADCNUM]; // Forward and reverse, so multiply by 2
static std::array<int32_t, SAMPLES_PER_LINE * NUM_OF_LINES * ADCNUM*2> stored_values;
static void init_measurements() { static size_t store_index = 0;
std::default_random_engine generator{}; static std::array<uint16_t, SAMPLES_PER_LINE * NUM_OF_LINES * ADCNUM*2*2> received_values;
std::normal_distribution<> dist{10000, 100}; static size_t pushed_index = 0;
std::random_device rd;
for (int i = 0; i < ADCNUM; i++) {
generator.seed(rd());
measured_values[i] = new int32_t[mod->max_lines_in][mod->max_samples_in];
for (int j = 0; j < mod->max_lines_in; j++) {
for (int k = 0; k < mod->max_samples_in; k++) {
measured_values[i][j][k] = dist(generator);
}
}
}
}
static void deinit_measurement() {
for (int i = 0; i < ADCNUM; i++) {
delete measured_values[i];
}
}
static std::array<uint16_t, 1 << MAX_BYTE_WID> fifo;
static uint32_t read_pos, write_pos;
static void handle_ram() { static void handle_ram() {
if (mod->ram_write && !mod->ram_valid) {
my_assert(pushed_index < received_values.max_size(), "pushed_index (%zu) maxed out", pushed_index);
received_values[pushed_index++] = mod->word;
mod->ram_valid = 1;
} else if (!mod->ram_write) {
mod->ram_valid = 0;
}
} }
static void handle_adc() { static void handle_adc() {
static int cntr[ADCNUM] = {0}; uint32_t tmp_adc_arm = mod->adc_arm;
static bool measuring[ADCNUM] = {0}; int i = 0;
static int amount_called = 0;
for (int i = 0; i < ADCNUM; i++) { if (mod->adc_arm && mod->adc_arm != mod->adc_finished) {
if (mod->adc_used_in & 1) { while (tmp_adc_arm) {
if (tmp_adc_arm & 1) {
my_assert(store_index < stored_values.max_size(),
"%d = %zu", store_index, stored_values.max_size());
uint32_t x = sign_extend(rand(), 24, false);
memcpy(&stored_values[store_index], &x, sizeof(x));
mod->adc_data[i] = stored_values[store_index];
store_index++;
}
i++;
tmp_adc_arm >>= 1;
}
mod->adc_finished = mod->adc_arm;
fprintf(stderr, "amount called: %d\n", ++amount_called);
} else if (!mod->adc_arm) {
mod->adc_finished = 0;
}
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
init(argc, argv); init(argc, argv);
init_values(); init_values();
init_measurements();
run_clock(); run_clock();
mod->arm = 1; write_raster_reg(RASTER_ARM, 1, 1, false);
while (!mod->finished) {
while (mod->is_running) {
run_clock(); run_clock();
handle_ram(); handle_ram();
handle_adc();
}
my_assert(pushed_index % 2 == 0, "uneven pushed index %d", pushed_index);
my_assert(store_index != pushed_index/2, "store_index (%d) != pushed_index/2(%d)\n", store_index, pushed_index/2);
my_assert(store_index == expected_store_index, "store_index (%zu) != (%zu)", store_index, expected_store_index);
exit(0);
for (size_t i = 0; i < pushed_index; i += 2) {
int32_t calcval = received_values[i+1] << 16 | received_values[i];
my_assert(calcval == stored_values[i/2], "calcval = %x, stored_values = %x", calcval, stored_values[i/2]);
} }
return 0; return 0;

View File

@ -2,23 +2,17 @@
`include "raster_cmds.vh" `include "raster_cmds.vh"
`include "ram_shim_cmds.vh" `include "ram_shim_cmds.vh"
module raster_sim #( module raster_sim #(
parameter SAMPLEWID = 9,
parameter DAC_DATA_WID = 20,
parameter DAC_WID = 24,
parameter DAC_WAIT_BETWEEN_CMD = 10, parameter DAC_WAIT_BETWEEN_CMD = 10,
parameter TIMER_WID = 4,
parameter STEPWID = 16,
parameter ADCNUM = 9,
parameter MAX_ADC_DATA_WID = 24,
parameter DAT_WID = 24, parameter DAT_WID = 24,
parameter RAM_WORD = 16, parameter RAM_WORD = 16,
parameter RAM_WID = 32, parameter RAM_WID = 32,
parameter RAM_SIM_WAIT_TIME = 54, parameter RAM_SIM_WAIT_TIME = 72,
parameter ADC_SIM_WAIT_TIME = 54 parameter ADC_SIM_WAIT_TIME = 54
) ( ) (
input clk, input clk,
output is_running,
input [`RASTER_CMD_WID-1:0] kernel_cmd, input [`RASTER_CMD_WID-1:0] kernel_cmd,
input [`RASTER_DATA_WID-1:0] kernel_data_in, input [`RASTER_DATA_WID-1:0] kernel_data_in,
@ -26,12 +20,12 @@ module raster_sim #(
input kernel_ready, input kernel_ready,
output kernel_finished, output kernel_finished,
output [DAC_DATA_WID-1:0] x_dac, output [`DAC_DATA_WID-1:0] x_dac,
output [DAC_DATA_WID-1:0] y_dac, output [`DAC_DATA_WID-1:0] y_dac,
output reg [ADCNUM-1:0] adc_arm, output reg [`ADCNUM-1:0] adc_arm,
input [MAX_ADC_DATA_WID-1:0] adc_data [ADCNUM-1:0], input [`MAX_ADC_DATA_WID-1:0] adc_data [`ADCNUM-1:0],
input [ADCNUM-1:0] adc_finished, input [`ADCNUM-1:0] adc_finished,
/* DMA interface */ /* DMA interface */
output [RAM_WORD-1:0] word, output [RAM_WORD-1:0] word,
@ -51,13 +45,15 @@ module raster_sim #(
* The code to handle each axis (X and Y) are similar. * The code to handle each axis (X and Y) are similar.
****/ ****/
reg [DAC_WID-1:0] coord_write_buf [1:0]; reg [`DAC_WID-1:0] coord_write_buf [1:0];
reg [DAC_WID-1:0] coord_to_dac [1:0]; /* verilator lint_off UNUSEDSIGNAL */
reg [DAC_WID-1:0] coord_from_dac [1:0]; reg [`DAC_WID-1:0] coord_to_dac [1:0];
/* verilator lint_on UNUSEDSIGNAL */
reg [`DAC_WID-1:0] coord_from_dac [1:0];
wire coord_arm [1:0]; wire coord_arm [1:0];
reg coord_finished [1:0]; reg coord_finished [1:0];
reg [DAC_DATA_WID-1:0] coord_dac [1:0]; reg [`DAC_DATA_WID-1:0] coord_dac [1:0];
assign x_dac = coord_dac[0]; assign x_dac = coord_dac[0];
assign y_dac = coord_dac[1]; assign y_dac = coord_dac[1];
@ -75,13 +71,13 @@ generate for (ci = 0; ci < 2; ci = ci + 1) begin
coord_to_dac[ci] <= coord_write_buf[ci]; coord_to_dac[ci] <= coord_write_buf[ci];
coord_finished[ci] <= 1; coord_finished[ci] <= 1;
case (coord_from_dac[ci][DAC_WID-1:DAC_WID-4]) case (coord_from_dac[ci][`DAC_WID-1:`DAC_DATA_WID])
4'b1001: begin 4'b1001: begin
coord_write_buf[ci] <= {4'b1001, coord_dac[ci]}; coord_write_buf[ci] <= {4'b1001, coord_dac[ci]};
end end
4'b0001: begin 4'b0001: begin
coord_write_buf[ci] <= 0; coord_write_buf[ci] <= 0;
coord_dac[ci] <= coord_from_dac[ci][DAC_WID-4-1:0]; coord_dac[ci] <= coord_from_dac[ci][`DAC_DATA_WID-1:0];
end end
default: ; default: ;
endcase endcase
@ -98,7 +94,7 @@ end endgenerate
* simulator so the C++ code doesn't have to implement timers manually. * simulator so the C++ code doesn't have to implement timers manually.
****/ ****/
wire [ADCNUM-1:0] adc_arm_internal; wire [`ADCNUM-1:0] adc_arm_internal;
reg [31:0] adc_wait_cntr = 0; reg [31:0] adc_wait_cntr = 0;
always @ (posedge clk) begin always @ (posedge clk) begin
@ -110,6 +106,7 @@ always @ (posedge clk) begin
end end
end else begin end else begin
adc_wait_cntr <= 0; adc_wait_cntr <= 0;
adc_arm <= 0;
end end
end end
@ -121,6 +118,7 @@ reg [31:0] ram_wait_cntr = 0;
always @ (posedge clk) begin always @ (posedge clk) begin
if (!ram_write_internal) begin if (!ram_write_internal) begin
ram_wait_cntr <= 0; ram_wait_cntr <= 0;
ram_write <= 0;
end else if (ram_wait_cntr < RAM_SIM_WAIT_TIME) begin end else if (ram_wait_cntr < RAM_SIM_WAIT_TIME) begin
ram_wait_cntr <= ram_wait_cntr + 1; ram_wait_cntr <= ram_wait_cntr + 1;
end else begin end else begin
@ -128,7 +126,7 @@ always @ (posedge clk) begin
end end
end end
wire [MAX_ADC_DATA_WID-1:0] ram_data; wire [`MAX_ADC_DATA_WID-1:0] ram_data;
wire ram_commit; wire ram_commit;
wire ram_finished; wire ram_finished;
@ -155,23 +153,18 @@ ram_shim #(
); );
/* Converting array to vector, arrays are easier to handle in Verilator. */ /* Converting array to vector, arrays are easier to handle in Verilator. */
wire [ADCNUM*MAX_ADC_DATA_WID-1:0] adc_data_internal; wire [`ADCNUM*`MAX_ADC_DATA_WID-1:0] adc_data_internal;
genvar ii; genvar ii;
generate for (ii = 0; ii < ADCNUM; ii = ii + 1) begin generate for (ii = 0; ii < `ADCNUM; ii = ii + 1) begin
assign adc_data_internal[(ii+1)*MAX_ADC_DATA_WID-1:ii*MAX_ADC_DATA_WID] assign adc_data_internal[(ii+1)*`MAX_ADC_DATA_WID-1:ii*`MAX_ADC_DATA_WID]
= adc_data[ii]; = adc_data[ii];
end endgenerate end endgenerate
raster #( raster #(
.SAMPLEWID(SAMPLEWID), .DAC_WAIT_BETWEEN_CMD(DAC_WAIT_BETWEEN_CMD)
.DAC_DATA_WID(DAC_DATA_WID),
.DAC_WID(DAC_WID),
.DAC_WAIT_BETWEEN_CMD(DAC_WAIT_BETWEEN_CMD),
.TIMER_WID(TIMER_WID),
.STEPWID(STEPWID),
.MAX_ADC_DATA_WID(MAX_ADC_DATA_WID)
) raster ( ) raster (
.clk(clk), .clk(clk),
.is_running(is_running),
.kernel_cmd(kernel_cmd), .kernel_cmd(kernel_cmd),
.kernel_data_in(kernel_data_in), .kernel_data_in(kernel_data_in),
@ -198,5 +191,10 @@ raster #(
.mem_finished(ram_finished) .mem_finished(ram_finished)
); );
initial begin
$dumpfile("raster.fst");
$dumpvars;
end
endmodule endmodule
`undefineall `undefineall