Skip to content

Commit

Permalink
Implement and test $mul. Use return, not exit in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
RCoeurjoly committed May 27, 2024
1 parent 761055a commit 03ae4c5
Show file tree
Hide file tree
Showing 33 changed files with 273 additions and 4 deletions.
3 changes: 2 additions & 1 deletion backends/functional/cxx.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ class CxxComputeGraphFactory {
T logical_shift_left(T a, T b, int y_width, int) { return graph.add(CxxFunction(ID($shl), y_width, {{ID(WIDTH), y_width}}), 0, std::array<T, 2>{a, b}); }
T logical_shift_right(T a, T b, int y_width, int) { return graph.add(CxxFunction(ID($shr), y_width, {{ID(WIDTH), y_width}}), 0, std::array<T, 2>{a, b}); }
T arithmetic_shift_right(T a, T b, int y_width, int) { return graph.add(CxxFunction(ID($asr), y_width, {{ID(WIDTH), y_width}}), 0, std::array<T, 2>{a, b}); }

T mul(T a, T b, int width) {return graph.add(CxxFunction(ID($mul), width), 0, std::array<T, 2>{a, b}); }

T constant(RTLIL::Const value) {
return graph.add(CxxFunction(ID($$const), value.size(), {{ID(value), value}}), 0);
}
Expand Down
14 changes: 14 additions & 0 deletions backends/functional/cxx_runtime/sim.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,4 +365,18 @@ Signal<n> $sign_extend(Signal<m> const& a)
return ret;
}

template<size_t n>
Signal<n> $mul(Signal<n> const& a, Signal<n> const& b)
{
Signal<n> ret = $const<n>(0);

for(size_t i = 0; i < n; i++) {
if(b[i]) {
Signal<n> shifted_a = $shl<n, n>($zero_extend<n, n>(a), $const<n>(i));
ret = $add(ret, shifted_a);
}
}
return ret;
}

#endif
3 changes: 2 additions & 1 deletion backends/functional/smtlib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,8 @@ class SmtlibComputeGraphFactory {
T logical_shift_left(T a, T b, int y_width, int b_width) { return shift("bvshl", a, b, y_width, b_width); }
T logical_shift_right(T a, T b, int y_width, int b_width) { return shift("bvlshl", a, b, y_width, b_width); }
T arithmetic_shift_right(T a, T b, int y_width, int b_width) { return shift("bvashr", a, b, y_width, b_width, true); }

T mul(T a, T b, int width) { return node(SExpr {"bvmul", Arg(1), Arg(2)}, width, {a, b}); }

T constant(RTLIL::Const value) { return node(SExpr(value), value.size(), {}); }
T input(IdString name, int width) {
module.input_struct.insert(name, width);
Expand Down
6 changes: 6 additions & 0 deletions kernel/graphtools.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ class CellSimplifier {
int offset = parameters.at(ID(OFFSET)).as_int();
T a = inputs.at(ID(A));
return factory.slice(a, a_width, offset, y_width);
}else if(cellType == ID($mul)){
bool is_signed = a_signed && b_signed;
int width = a_width + b_width;
T a = extend(inputs.at(ID(A)), a_width, width, is_signed);
T b = extend(inputs.at(ID(B)), b_width, width, is_signed);
return extend(factory.mul(a, b, width), width, y_width, is_signed);
}else{
log_error("unhandled cell in CellSimplifier %s\n", cellType.c_str());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

set -ex

# Define the common variable for the relative path
BASE_PATH="../../../"

# Initialize an array to store the names of failing Verilog files and their failure types
declare -A failing_files

Expand All @@ -11,11 +14,11 @@ for verilog_file in verilog/*.v; do
base_name=$(basename "$verilog_file" .v)

# Run yosys to process each Verilog file
if ../../yosys -p "read_verilog $verilog_file; write_cxxrtl my_module_cxxrtl.cc; write_functional_cxx my_module_functional_cxx.cc"; then
if ${BASE_PATH}yosys -p "read_verilog $verilog_file; write_cxxrtl my_module_cxxrtl.cc; write_functional_cxx my_module_functional_cxx.cc"; then
echo "Yosys processed $verilog_file successfully."

# Compile the generated C++ files with vcd_harness.cpp
${CXX:-g++} -g -fprofile-arcs -ftest-coverage vcd_harness.cpp -I ../../backends/functional/cxx_runtime/ -I ../../backends/cxxrtl/runtime/ -o vcd_harness
${CXX:-g++} -g -fprofile-arcs -ftest-coverage vcd_harness.cpp -I ${BASE_PATH}backends/functional/cxx_runtime/ -I ${BASE_PATH}backends/cxxrtl/runtime/ -o vcd_harness

# Generate VCD files with base_name
if ./vcd_harness ${base_name}_functional_cxx.vcd ${base_name}_cxxrtl.vcd ; then
Expand Down
133 changes: 133 additions & 0 deletions tests/functional/multi_bit/vcd_harness.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include <cstdio>
#include <iostream>
#include <fstream>
#include <random>

#include <cxxrtl/cxxrtl_vcd.h>

#include "my_module_cxxrtl.cc"
#include "my_module_functional_cxx.cc"

struct DumpHeader {
std::ofstream &ofs;
DumpHeader(std::ofstream &ofs) : ofs(ofs) {}
template <size_t n>
void operator()(const char *name, Signal<n> value) {
ofs << "$var wire " << n << " " << name[0] << " " << name << " $end\n";
}
};

struct Dump {
std::ofstream &ofs;
Dump(std::ofstream &ofs) : ofs(ofs) {}
template <size_t n>
void operator()(const char *name, Signal<n> value) {
// Bit
if (n == 1) {
ofs << (value[0] ? '1' : '0');
ofs << name[0] << "\n";
return;
}
// vector (multi-bit) signals
ofs << "b";
for (size_t i = n; i-- > 0;)
ofs << (value[i] ? '1' : '0');
ofs << " " << name[0] << "\n";
}
};

int main(int argc, char **argv)
{
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " <functional_vcd_filename> <cxxrtl_vcd_filename>\n";
return 1;
}

const std::string functional_vcd_filename = argv[1];
const std::string cxxrtl_vcd_filename = argv[2];

constexpr int steps = 10;
constexpr int number_timescale = 1;
const std::string units_timescale = "us";
my_module_Inputs inputs;
my_module_Outputs outputs;
my_module_State state;
my_module_State next_state;

std::ofstream vcd_file(functional_vcd_filename);

vcd_file << "$timescale " << number_timescale << " " << units_timescale << " $end\n";
{
DumpHeader d(vcd_file);
inputs.dump(d);
outputs.dump(d);
state.dump(d);
}
vcd_file << "$enddefinitions $end\n$dumpvars\n";

cxxrtl_design::p_my__module top;

cxxrtl::debug_items all_debug_items;
cxxrtl::debug_scope debug_scope;
top.debug_info(&all_debug_items, nullptr, "");

cxxrtl::vcd_writer vcd;
vcd.timescale(number_timescale, units_timescale);
vcd.add_without_memories(all_debug_items);

std::ofstream waves(cxxrtl_vcd_filename);

top.p_a.set<8>(false);
top.p_b.set<8>(false);
top.step();

vcd.sample(0);
vcd_file << "#0\n";
inputs.a = $const<8>(false);
inputs.b = $const<8>(false);
my_module(inputs, outputs, state, next_state);
{
Dump d(vcd_file);
inputs.dump(d);
outputs.dump(d);
state.dump(d);
}

std::random_device rd;
std::mt19937 gen(rd());
std::bernoulli_distribution dist(0.5);

for (int step = 0; step < steps; ++step) {
const bool a_value = dist(gen);
const bool b_value = dist(gen);

// cxxrtl
top.p_a.set<bool>(a_value);
top.p_b.set<bool>(b_value);
top.step();
vcd.sample(step + 1);

waves << vcd.buffer;
vcd.buffer.clear();

// Functional backend cxx
vcd_file << "#" << (step + 1) << "\n";
inputs.a = $const<8>(a_value);
inputs.b = $const<8>(b_value);

my_module(inputs, outputs, state, next_state);
{
Dump d(vcd_file);
inputs.dump(d);
outputs.dump(d);
state.dump(d);
}

state = next_state;
}

vcd_file.close();
waves.close();

return 0;
}
9 changes: 9 additions & 0 deletions tests/functional/multi_bit/verilog/and.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module my_module(
input [7:0] a,
input [7:0] b,
output [7:0] y
);
// Perform bitwise AND
assign y = a & b;

endmodule
69 changes: 69 additions & 0 deletions tests/functional/single_bit/run-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash

# Initialize an array to store the names of failing Verilog files and their failure types
declare -A failing_files

# Function to run the test on a given Verilog file
run_test() {
# Define the common variable for the relative path
BASE_PATH="../../../"

local verilog_file=$1

# Extract the base name without extension
local base_name=$(basename "$verilog_file" .v)

# Run yosys to process each Verilog file
if ${BASE_PATH}yosys -p "read_verilog $verilog_file; write_cxxrtl my_module_cxxrtl.cc; write_functional_cxx my_module_functional_cxx.cc"; then
echo "Yosys processed $verilog_file successfully."

# Compile the generated C++ files with vcd_harness.cpp
${CXX:-g++} -g -fprofile-arcs -ftest-coverage vcd_harness.cpp -I ${BASE_PATH}backends/functional/cxx_runtime/ -I ${BASE_PATH}backends/cxxrtl/runtime/ -o vcd_harness

# Generate VCD files with base_name
if ./vcd_harness ${base_name}_functional_cxx.vcd ${base_name}_cxxrtl.vcd ; then
# Run vcdiff and capture the output
local output=$(vcdiff ${base_name}_functional_cxx.vcd ${base_name}_cxxrtl.vcd)

# Check if there is any output
if [ -n "$output" ]; then
echo "Differences detected in $verilog_file:"
echo "$output"
failing_files["$verilog_file"]="Differences detected"
else
echo "No differences detected in $verilog_file."
fi
else
echo "Failed to generate VCD files for $verilog_file."
failing_files["$verilog_file"]="VCD generation failure"
fi
else
echo "Yosys failed to process $verilog_file."
failing_files["$verilog_file"]="Yosys failure"
fi
}

# Main function to run all tests
run_all_tests() {
# Loop through all Verilog files in the verilog directory
for verilog_file in verilog/*.v; do
run_test "$verilog_file"
done

# Check if the array of failing files is empty
if [ ${#failing_files[@]} -eq 0 ]; then
echo "All files passed."
return 0
else
echo "The following files failed:"
for file in "${!failing_files[@]}"; do
echo "$file: ${failing_files[$file]}"
done
return 1
fi
}

# If the script is being sourced, do not execute the tests
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
run_all_tests
fi
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
33 changes: 33 additions & 0 deletions tests/verismith/yosys_all.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[probability]
expr.binary = 5
expr.concatenation = 5
expr.number = 1
expr.rangeselect = 5
expr.signed = 5
expr.string = 0
expr.ternary = 5
expr.unary = 5
expr.unsigned = 5
expr.variable = 5
moditem.assign = 2
moditem.combinational = 0
moditem.instantiation = 0
moditem.sequential = 3
statement.blocking = 0
statement.conditional = 1
statement.forloop = 0
statement.nonblocking = 2

[property]
module.depth = 2
module.max = 5
size = 20
statement.depth = 7
sample.method = "hat"
sample.size = 10

[[synthesiser]]
name = "yosys"
description = "yosys_nix"
output = "yosys_nix.v"
bin = "/nix/store/fzqckbn2ajj6illgrbcja6fj8qzrbacb-yosys/bin/"

0 comments on commit 03ae4c5

Please sign in to comment.