Skip to content

Commit

Permalink
Binary-based initialization of generated testbench (ferrandi#93)
Browse files Browse the repository at this point in the history
Added support for binary-based initialization of generated testbench.

Co-authored-by: Michele Fiorito <[email protected]>
  • Loading branch information
fabrizioferrandi and Ansaya authored Nov 22, 2022
1 parent 691ca73 commit be620f7
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 54 deletions.
16 changes: 9 additions & 7 deletions etc/scripts/test_panda.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ def __call__(self, parser, namespace, values, option_string=None):
def GetChildren(parent_pid):
ret = set()
ps_command = subprocess.Popen(
"ps -o pid --ppid %d --noheaders" % parent_pid, shell=True, stdout=subprocess.PIPE)
ps_output = ps_command.stdout.read()
"ps --ppid %d -o pid=" % parent_pid, shell=True, stdout=subprocess.PIPE)
ps_command.wait()
for pid_str in ps_output.split("\n")[:-1]:
ret.add(int(pid_str))
ps_output = ps_command.stdout.read().decode()
for pid_str in ps_output.split('\n')[:-1]:
ret.add(int(pid_str, base=10))
return ret

# Kill a process than kill its children
Expand Down Expand Up @@ -1093,19 +1093,21 @@ def CreatePerfPublisherBody(directory, pp_file):
try:
# Wait threads
for thread_index in range(n_jobs):
while threads[thread_index].is_alive():
while threads[thread_index].isAlive():
threads[thread_index].join(100)
except KeyboardInterrupt:
logging.error("SIGINT received")
failure = True
with lock_creation_destruction:
failure = True
args.stop = True
for local_thread_index in range(n_jobs):
if children[local_thread_index] != None:
if children[local_thread_index].poll() == None:
try:
kill_proc_tree(children[local_thread_index].pid)
except OSError:
pass
sys.exit(1)
# sys.exit(1)

# Collect results
CollectResults(abs_path)
Expand Down
2 changes: 1 addition & 1 deletion panda_regressions/hls/bambu_specific_test2_list
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ bambu_specific_test2/port_swapping_test2.c --top-fname=function bambu_specific_t
bambu_specific_test2/complex_test.c --top-fname=sum --generate-tb=BENCHMARKS_ROOT/bambu_specific_test2/complex_test.xml --experimental-setup=BAMBU
bambu_specific_test2/multiarray.c --top-fname=fun2 --generate-tb=arr1="{{{3,0},{0,0}},{{8,3},{8,0}}}",arr2="{{{5,2},{0,1}},{{7,3},{5,0}}}",arr3="{{{3,0},{7,0}},{{3,5},{0,0}}}" --std=c99 --experimental-setup=BAMBU
bambu_specific_test2/test_without_c.c --top-fname=function --generate-tb=BENCHMARKS_ROOT/bambu_specific_test2/test_without_c.xml --experimental-setup=BAMBU-BALANCED-MP
bambu_specific_test2/mod_test.c --top-fname=test --generate-tb=BENCHMARKS_ROOT/bambu_specific_test2/mod_test_c.xml
bambu_specific_test2/mod_test.c --top-fname=test --generate-tb=BENCHMARKS_ROOT/bambu_specific_test2/mod_test_c.xml
Binary file not shown.
4 changes: 4 additions & 0 deletions panda_regressions/hls/bambu_specific_test6/bin_test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<function>
<testbench a_ptr:init_file="bin_test.dat"/>
</function>
12 changes: 12 additions & 0 deletions panda_regressions/hls/bambu_specific_test6/bin_testbench.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
typedef struct c_t {
unsigned nrow;
unsigned nnz;
float value[20];
unsigned cindex[20];
unsigned rowstart[20];
} complex_t;

unsigned kernel(complex_t*a_ptr)
{
return a_ptr->value[1];
}
2 changes: 2 additions & 0 deletions panda_regressions/hls/bambu_specific_test6_list
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,5 @@ bambu_specific_test6/insert_extract_element.ll --benchmark-name=insert_extract3
bambu_specific_test6/insert_extract_element.ll --benchmark-name=insert_extract3_output_c --top-fname=test3 --generate-tb="P0=1,P1=2,P2=3,P3=4,P4=5,P5=6,P6=7,P7=8" --pretty-print=output.c --max-transformations=0
bambu_specific_test6/insert_extract_element.ll --benchmark-name=insert_extract4 --top-fname=test3 --generate-tb="P0=1,P1=2,P2=3,P3=4,P4=5,P5=6,P6=7,P7=8"
bambu_specific_test6/insert_extract_element.ll --benchmark-name=insert_extract4_output_c --top-fname=test3 --generate-tb="P0=1,P1=2,P2=3,P3=4,P4=5,P5=6,P6=7,P7=8" --pretty-print=output.c

bambu_specific_test6/bin_testbench.c --top-fname=kernel --generate-tb=BENCHMARKS_ROOT/bambu_specific_test6/bin_test.xml --experimental-setup=BAMBU-BALANCED-MP --file-input-data=BENCHMARKS_ROOT/bambu_specific_test6/bin_test.dat
10 changes: 4 additions & 6 deletions src/HLS/simulation/testbench_generation_base_step.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,7 @@ void TestbenchGenerationBaseStep::write_output_checks(const tree_managerConstRef
auto InterfaceType = GetPointer<port_o>(portInst)->get_port_interface();
if(InterfaceType == port_o::port_interface::PI_DOUT)
{
const auto manage_pidout = [&](const std::string& portID)
{
const auto manage_pidout = [&](const std::string& portID) {
auto port_name = portInst->get_id();
auto terminate = port_name.size() > 3 ? port_name.size() - std::string("_d" + portID).size() : 0;
THROW_ASSERT(port_name.substr(terminate) == "_d" + portID, "inconsistent interface");
Expand Down Expand Up @@ -640,8 +639,7 @@ void TestbenchGenerationBaseStep::write_output_checks(const tree_managerConstRef
auto InterfaceType = GetPointer<port_o>(portInst)->get_port_interface();
if(InterfaceType == port_o::port_interface::PI_DIN)
{
const auto manage_pidin = [&](const std::string& portID)
{
const auto manage_pidin = [&](const std::string& portID) {
auto port_name = portInst->get_id();
auto terminate = port_name.size() > 3 ? port_name.size() - std::string("_q" + portID).size() : 0;
THROW_ASSERT(port_name.substr(terminate) == "_q" + portID, "inconsistent interface");
Expand Down Expand Up @@ -896,7 +894,7 @@ void TestbenchGenerationBaseStep::write_output_checks(const tree_managerConstRef
{
if(output_level >= OUTPUT_LEVEL_VERY_PEDANTIC)
{
writer->write("$display(\" comparision = %b " + nonescaped_name +
writer->write("$display(\" comparison = %b " + nonescaped_name +
" = %d "
" _bambu_testbench_mem_[" +
nonescaped_name + " + %d - base_addr] = %20.20f expected = %20.20f \", ");
Expand Down Expand Up @@ -1619,7 +1617,7 @@ void TestbenchGenerationBaseStep::write_output_checks(const tree_managerConstRef
{
if(output_level > OUTPUT_LEVEL_MINIMUM)
{
writer->write("$display(\" comparision = %b " + nonescaped_name +
writer->write("$display(\" comparison%b " + nonescaped_name +
" = %d "
" _bambu_testbench_mem_[" +
nonescaped_name + " + %d - base_addr] = %20.20f expected = %20.20f \", ");
Expand Down
7 changes: 6 additions & 1 deletion src/HLS/simulation/testbench_memory_allocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,12 @@ void TestbenchMemoryAllocation::AllocTestbenchMemory(void) const
if(tree_helper::IsPointerType(lnode) && !is_memory)
{
const auto pt_node = tree_helper::CGetType(lnode);
if(flag_cpp)
if(test_v.size() > 4 && test_v.substr(test_v.size() - 4) == ".dat")
{
std::ifstream in(test_v, std::ifstream::ate | std::ifstream::binary);
reserved_bytes = static_cast<unsigned>(in.tellg());
}
else if(flag_cpp)
{
tree_nodeConstRef ptd_base_type;
if(GET_CONST_NODE(pt_node)->get_kind() == pointer_type_K)
Expand Down
4 changes: 2 additions & 2 deletions src/HLS/simulation/testbench_values_xml_generation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ DesignFlowStep_Status TestbenchValuesXMLGeneration::Exec()
}
else
{
/// Call the parser to translate C initialization to verilog initialization
/// Call the parser to translate C initialization to Verilog initialization
const CInitializationParserFunctorRef c_initialization_parser_functor =
CInitializationParserFunctorRef(new MemoryInitializationWriter(
output_stream, TM, behavioral_helper, reserved_mem_bytes, TM->CGetTreeReindex(l),
Expand All @@ -309,7 +309,7 @@ DesignFlowStep_Status TestbenchValuesXMLGeneration::Exec()
output_stream << "m00000000" << std::endl;
}
}
INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Cosidered parameter '" + param + "'");
INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered parameter '" + param + "'");
}
++v_idx;
INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "<--Considered vector");
Expand Down
107 changes: 71 additions & 36 deletions src/design_flows/backend/ToC/source_code_writers/hls_c_writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ void HLSCWriter::WriteParamInitialization(const BehavioralHelperConstRef behavio
"_size, " + fp + ") != " + param + "_size)\n");
indented_output_stream->Append("{\n");
indented_output_stream->Append("fclose(" + fp + ");\n");
indented_output_stream->Append("printf(\"Unable to read " + test_v + " to initialise parameter " + param +
indented_output_stream->Append("printf(\"Unable to read " + test_v + " to initialize parameter " + param +
"\");\n");
indented_output_stream->Append("exit(-1);\n");
indented_output_stream->Append("}\n");
Expand Down Expand Up @@ -892,7 +892,7 @@ void HLSCWriter::WriteExpectedResults(const BehavioralHelperConstRef behavioral_
indented_output_stream->Append("{\n");
}
WriteParamInMemory(behavioral_helper, param + (reference_type_p ? "" : "[i0]"),
pointedType_node->index, 1, false);
pointedType_node->index, 1, false, false);
if(num_elements > 1 || !reference_type_p)
{
indented_output_stream->Append("}\n");
Expand Down Expand Up @@ -947,14 +947,14 @@ void HLSCWriter::WriteExpectedResults(const BehavioralHelperConstRef behavioral_
const auto num_elements = reserved_mem_bytes / element_size;
THROW_ASSERT(num_elements, STR(reserved_mem_bytes) + "/" + STR(element_size));
indented_output_stream->Append("{\n");
indented_output_stream->Append("int i0;\n");
indented_output_stream->Append("int i0=0;\n");
if(num_elements > 1 || !reference_type_p)
{
indented_output_stream->Append("for(i0 = 0; i0 < " + STR(num_elements) + "; i0++)\n");
indented_output_stream->Append("{\n");
}
WriteParamInMemory(behavioral_helper, param + (reference_type_p ? "" : "[i0]"), pointedType_node->index, 1,
false);
false, false);
if(num_elements > 1 || !reference_type_p)
{
indented_output_stream->Append("}\n");
Expand Down Expand Up @@ -1066,6 +1066,7 @@ void HLSCWriter::WriteSimulatorInitMemory(const unsigned int function_id)

bool is_memory = false;
std::string test_v;
bool binary_test_v = false;
if(mem_vars.find(l) != mem_vars.end() && !is_interface)
{
is_memory = true;
Expand All @@ -1079,34 +1080,41 @@ void HLSCWriter::WriteSimulatorInitMemory(const unsigned int function_id)
else if(curr_test_vector.find(param) != curr_test_vector.end())
{
test_v = curr_test_vector.find(param)->second;
if(flag_cpp)
if(test_v.size() < 4 || test_v.substr(test_v.size() - 4) != ".dat")
{
/// Remove leading spaces
test_v.erase(0, test_v.find_first_not_of(" \t"));
/// Remove trailing spaces
auto last_character = test_v.find_last_not_of(" \t");
if(std::string::npos != last_character)
if(flag_cpp)
{
test_v.erase(last_character + 1);
}
/// Remove first {
if(test_v.front() == '{')
{
test_v.erase(0, 1);
/// Remove leading spaces
test_v.erase(0, test_v.find_first_not_of(" \t"));
/// Remove trailing spaces
auto last_character = test_v.find_last_not_of(" \t");
if(std::string::npos != last_character)
{
test_v.erase(last_character + 1);
}
/// Remove first {
if(test_v.front() == '{')
{
test_v.erase(0, 1);
}
/// Remove last }
if(test_v.back() == '}')
{
test_v.pop_back();
}
}
/// Remove last }
if(test_v.back() == '}')
else
{
test_v.pop_back();
if(test_v.front() != '{' && test_v.back() != '}')
{
test_v = std::string("{") + test_v;
test_v = test_v + "}";
}
}
}
else
{
if(test_v.front() != '{' && test_v.back() != '}')
{
test_v = std::string("{") + test_v;
test_v = test_v + "}";
}
binary_test_v = true;
}
}
else if(flag_cpp)
Expand All @@ -1125,8 +1133,7 @@ void HLSCWriter::WriteSimulatorInitMemory(const unsigned int function_id)
}

/// Retrieve the space to be reserved in memory
const auto reserved_mem_bytes = [&]() -> size_t
{
const auto reserved_mem_bytes = [&]() -> size_t {
if(is_memory)
{
const auto ret_value = tree_helper::Size(TM->CGetTreeReindex(l)) / 8;
Expand All @@ -1143,15 +1150,41 @@ void HLSCWriter::WriteSimulatorInitMemory(const unsigned int function_id)
"---Symbol: " + param + " Reserved memory " + STR(reserved_mem_bytes) + " - Test vector is " +
test_v);

/// FIXME: for c++ code the old code is still used
if(flag_cpp || is_memory)
if(binary_test_v)
{
const auto fp = param + "_fp_local";
indented_output_stream->Append("FILE* " + fp + " = fopen(\"" + test_v + "\", \"rb\");\n");
indented_output_stream->Append("fseek(" + fp + ", 0, SEEK_END);\n");
indented_output_stream->Append("size_t " + param + "_size = ftell(" + fp + ");\n");
indented_output_stream->Append("fseek(" + fp + ", 0, SEEK_SET);\n");
indented_output_stream->Append("unsigned char* " + param + "_buf_local = (unsigned char*)malloc(" + param +
"_size);\n");
indented_output_stream->Append("if(fread(" + param + "_buf_local, sizeof *" + param + "_buf_local, " +
param + "_size, " + fp + ") != " + param + "_size)\n");
indented_output_stream->Append("{\n");
indented_output_stream->Append("fclose(" + fp + ");\n");
indented_output_stream->Append("printf(\"Unable to read " + test_v + " to initialize parameter " + param +
"\");\n");
indented_output_stream->Append("exit(-1);\n");
indented_output_stream->Append("}\n");
indented_output_stream->Append("fclose(" + fp + ");\n");
indented_output_stream->Append(
"for (__testbench_index = 0; "
"__testbench_index < " +
param + "_size; " +
"++__testbench_index){\n fprintf(__bambu_testbench_fp, \"m\");\n _Dec2Bin_(__bambu_testbench_fp," +
param + "_buf_local[__testbench_index], 8);\n");
indented_output_stream->Append("}\n");
INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level,
"---Using a binary file for " + param + " - " + test_v);
}
else if(flag_cpp || is_memory) /// FIXME: for c++ code the old code is still used
{
size_t printed_bytes = 0;
std::string bits_offset = "";
std::vector<std::string> splitted = SplitString(test_v, ",");
INDENT_DBG_MEX(DEBUG_LEVEL_VERY_PEDANTIC, debug_level, "---Processing c++ init " + test_v);
const auto isAllZero = [&]() -> bool
{
const auto isAllZero = [&]() -> bool {
if(splitted.size() == 0)
{
return false;
Expand Down Expand Up @@ -1635,7 +1668,8 @@ void HLSCWriter::WriteBuiltinWaitCall()
}

void HLSCWriter::WriteParamInMemory(const BehavioralHelperConstRef behavioral_helper, const std::string& param,
const unsigned int type_index, const unsigned int nesting_level, bool input)
const unsigned int type_index, const unsigned int nesting_level, bool input,
bool is_struct_or_union)
{
const auto type = TM->CGetTreeNode(type_index);
switch(type->get_kind())
Expand All @@ -1646,12 +1680,13 @@ void HLSCWriter::WriteParamInMemory(const BehavioralHelperConstRef behavioral_he
indented_output_stream->Append("fprintf(__bambu_testbench_fp, \"//expected value for output: " + param +
"\\n\");\n");
const auto size = tree_helper::Size(type);
if(input)
if(input || is_struct_or_union) // Checking ULP on expected floating point fields is not possible
{
const auto byte_size = tree_helper::Size(type) / 8;
for(size_t byte = 0; byte < byte_size; byte++)
{
indented_output_stream->Append("fprintf(__bambu_testbench_fp, \"m\");\n");
indented_output_stream->Append("fprintf(__bambu_testbench_fp, \"" + std::string(input ? "m" : "o") +
"\");\n");
indented_output_stream->Append("_Ptd2Bin_(__bambu_testbench_fp, ((unsigned char *)&(" + param + ")) + " +
STR(byte) + ", 8);\n");
indented_output_stream->Append("fprintf(__bambu_testbench_fp, \"\\n\");\n");
Expand Down Expand Up @@ -1689,7 +1724,7 @@ void HLSCWriter::WriteParamInMemory(const BehavioralHelperConstRef behavioral_he
{
const auto field_param = param + "." + behavioral_helper->PrintVariable(field->index);
WriteParamInMemory(behavioral_helper, field_param, tree_helper::get_type_index(TM, field->index),
nesting_level + 1, input);
nesting_level + 1, input, true);
}
break;
}
Expand All @@ -1700,7 +1735,7 @@ void HLSCWriter::WriteParamInMemory(const BehavioralHelperConstRef behavioral_he
{
const auto field_param = param + "." + behavioral_helper->PrintVariable(field->index);
WriteParamInMemory(behavioral_helper, field_param, tree_helper::get_type_index(TM, field->index),
nesting_level + 1, input);
nesting_level + 1, input, true);
break; // only the first field will be considered
}
break;
Expand All @@ -1723,7 +1758,7 @@ void HLSCWriter::WriteParamInMemory(const BehavioralHelperConstRef behavioral_he
"; " + variable_name + "++)\n");
indented_output_stream->Append("{\n");
WriteParamInMemory(behavioral_helper, param + "[" + variable_name + "]", array_t->index, nesting_level + 1,
input);
input, is_struct_or_union);
indented_output_stream->Append("}\n");
indented_output_stream->Append("}\n");
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class HLSCWriter : public CWriter
* @param input specifies if the input syntax must be used
*/
void WriteParamInMemory(const BehavioralHelperConstRef behavioral_helper, const std::string& param,
const unsigned int type, const unsigned int nesting_level, bool input);
const unsigned int type, const unsigned int nesting_level, bool input, bool is_struct_or_union);

public:
/**
Expand Down

0 comments on commit be620f7

Please sign in to comment.