From 671188dfa4578c7b07183e58c0b6e2a6dcee8535 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Feb 2022 23:05:03 -0800 Subject: [PATCH 1/5] [FPGA-Verilog] Now support big/little-endian in bus group --- libopenfpga/libbusgroup/src/bus_group.cpp | 12 ++++++++++++ libopenfpga/libbusgroup/src/bus_group.h | 9 +++++++++ .../libbusgroup/src/bus_group_xml_constants.h | 1 + libopenfpga/libbusgroup/src/read_xml_bus_group.cpp | 3 +++ libopenfpga/libbusgroup/src/write_xml_bus_group.cpp | 1 + .../fpga_verilog/verilog_preconfig_top_module.cpp | 5 ++++- openfpga/src/fpga_verilog/verilog_writer_utils.cpp | 10 ++++++++-- openfpga/src/fpga_verilog/verilog_writer_utils.h | 3 ++- 8 files changed, 40 insertions(+), 4 deletions(-) diff --git a/libopenfpga/libbusgroup/src/bus_group.cpp b/libopenfpga/libbusgroup/src/bus_group.cpp index 7aed69215..8bc5688ed 100644 --- a/libopenfpga/libbusgroup/src/bus_group.cpp +++ b/libopenfpga/libbusgroup/src/bus_group.cpp @@ -33,6 +33,11 @@ openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const { return bus_ports_[bus_id]; } +bool BusGroup::is_big_endian(const BusGroupId& bus_id) const { + VTR_ASSERT(valid_bus_id(bus_id)); + return bus_big_endians_[bus_id]; +} + std::vector BusGroup::bus_pins(const BusGroupId& bus_id) const { VTR_ASSERT(valid_bus_id(bus_id)); return bus_pin_ids_[bus_id]; @@ -89,6 +94,7 @@ bool BusGroup::empty() const { void BusGroup::reserve_buses(const size_t& num_buses) { bus_ids_.reserve(num_buses); bus_ports_.reserve(num_buses); + bus_big_endians_.reserve(num_buses); bus_pin_ids_.reserve(num_buses); } @@ -105,6 +111,7 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { bus_ids_.push_back(bus_id); bus_ports_.push_back(bus_port); + bus_big_endians_.push_back(true); bus_pin_ids_.emplace_back(); /* Register to fast look-up */ @@ -119,6 +126,11 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { return bus_id; } +void BusGroup::set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian) { + VTR_ASSERT(valid_bus_id(bus_id)); + bus_big_endians_[bus_id] = big_endian; +} + BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) { /* Create a new id */ BusPinId pin_id = BusPinId(pin_ids_.size()); diff --git a/libopenfpga/libbusgroup/src/bus_group.h b/libopenfpga/libbusgroup/src/bus_group.h index da63fb210..85d80c579 100644 --- a/libopenfpga/libbusgroup/src/bus_group.h +++ b/libopenfpga/libbusgroup/src/bus_group.h @@ -50,6 +50,9 @@ class BusGroup { /** Get port information of a bus with a given id */ BasicPort bus_port(const BusGroupId& bus_id) const; + /* Check if a bus follows big endian */ + bool is_big_endian(const BusGroupId& bus_id) const; + /* Get the pins under a specific bus */ std::vector bus_pins(const BusGroupId& bus_id) const; @@ -81,6 +84,9 @@ class BusGroup { /* Add a bus to storage */ BusGroupId create_bus(const openfpga::BasicPort& bus_port); + /* Set endianness for a bus; If not set, by default it assumes big-endian */ + void set_bus_big_endian(const BusGroupId& bus_id, const bool& big_endian); + /* Add a pin to a bus, with a given index in the bus, e.g., A[1] in A[0:2] */ BusPinId create_pin(const BusGroupId& bus_id, const int& index); @@ -101,6 +107,9 @@ class BusGroup { /* Port information of each bus */ vtr::vector bus_ports_; + /* Endianness of each bus: big endian by default */ + vtr::vector bus_big_endians_; + /* Indices of each pin under each bus */ vtr::vector> bus_pin_ids_; diff --git a/libopenfpga/libbusgroup/src/bus_group_xml_constants.h b/libopenfpga/libbusgroup/src/bus_group_xml_constants.h index 9f27ae978..62b552f06 100644 --- a/libopenfpga/libbusgroup/src/bus_group_xml_constants.h +++ b/libopenfpga/libbusgroup/src/bus_group_xml_constants.h @@ -6,6 +6,7 @@ constexpr char* XML_BUS_GROUP_NODE_NAME = "bus_group"; constexpr char* XML_BUS_NODE_NAME = "bus"; constexpr char* XML_BUS_PORT_ATTRIBUTE_NAME = "name"; +constexpr char* XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME = "big_endian"; constexpr char* XML_PIN_NODE_NAME = "pin"; constexpr char* XML_PIN_INDEX_ATTRIBUTE_NAME = "id"; constexpr char* XML_PIN_NAME_ATTRIBUTE_NAME = "name"; diff --git a/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp index 020aa224b..768ff455a 100644 --- a/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp +++ b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp @@ -76,6 +76,9 @@ void read_xml_bus(pugi::xml_node& xml_bus, "Bus port is invalid, check LSB and MSB!\n"); } + /* Find big endian */ + bus_group.set_bus_big_endian(bus_id, get_attribute(xml_bus, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, loc_data, pugiutil::OPTIONAL).as_bool(true)); + for (pugi::xml_node xml_pin : xml_bus.children()) { /* Error out if the XML child has an invalid name! */ if (xml_pin.name() != std::string(XML_PIN_NODE_NAME)) { diff --git a/libopenfpga/libbusgroup/src/write_xml_bus_group.cpp b/libopenfpga/libbusgroup/src/write_xml_bus_group.cpp index 9d9fdb005..be26b44f5 100644 --- a/libopenfpga/libbusgroup/src/write_xml_bus_group.cpp +++ b/libopenfpga/libbusgroup/src/write_xml_bus_group.cpp @@ -46,6 +46,7 @@ int write_xml_bus(std::fstream& fp, } write_xml_attribute(fp, XML_BUS_PORT_ATTRIBUTE_NAME, generate_xml_port_name(bus_group.bus_port(bus_id)).c_str()); + write_xml_attribute(fp, XML_BUS_BIG_ENDIAN_ATTRIBUTE_NAME, bus_group.is_big_endian(bus_id)); fp << ">" << "\n"; /* Output all the pins under this bus */ diff --git a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp index 26ce11c2f..fba957963 100644 --- a/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp +++ b/openfpga/src/fpga_verilog/verilog_preconfig_top_module.cpp @@ -56,6 +56,7 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, /* Ports to be added, this is to avoid any bus port */ std::vector port_list; std::vector port_types; + std::vector port_big_endian; /* Print all the I/Os of the circuit implementation to be tested*/ for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) { @@ -96,6 +97,7 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, if (port_list.end() == std::find(port_list.begin(), port_list.end(), bus_group.bus_port(bus_id))) { port_list.push_back(bus_group.bus_port(bus_id)); port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); + port_big_endian.push_back(bus_group.is_big_endian(bus_id)); } continue; } @@ -104,6 +106,7 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, BasicPort module_port(std::string(block_name), 1); port_list.push_back(module_port); port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); + port_big_endian.push_back(true); } /* After collecting all the ports, now print the port mapping */ @@ -115,7 +118,7 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp, fp << "," << std::endl; } - fp << generate_verilog_port(port_type2type_map[port_type], module_port); + fp << generate_verilog_port(port_type2type_map[port_type], module_port, true, port_big_endian[iport]); /* Update port counter */ port_counter++; diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp index ea34f35b7..d537b89f3 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.cpp @@ -466,13 +466,19 @@ void print_verilog_module_end(std::fstream& fp, ***********************************************/ std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type, const BasicPort& port_info, - const bool& must_print_port_size) { + const bool& must_print_port_size, + const bool& big_endian) { std::string verilog_line; /* Ensure the port type is valid */ VTR_ASSERT(verilog_port_type < NUM_VERILOG_PORT_TYPES); - std::string size_str = "[" + std::to_string(port_info.get_lsb()) + ":" + std::to_string(port_info.get_msb()) + "]"; + std::string size_str; + if (big_endian) { + size_str = "[" + std::to_string(port_info.get_lsb()) + ":" + std::to_string(port_info.get_msb()) + "]"; + } else { + size_str = "[" + std::to_string(port_info.get_msb()) + ":" + std::to_string(port_info.get_lsb()) + "]"; + } /* Only connection require a format of [:] * others require a format of [:] diff --git a/openfpga/src/fpga_verilog/verilog_writer_utils.h b/openfpga/src/fpga_verilog/verilog_writer_utils.h index af344e146..180df8e45 100644 --- a/openfpga/src/fpga_verilog/verilog_writer_utils.h +++ b/openfpga/src/fpga_verilog/verilog_writer_utils.h @@ -87,7 +87,8 @@ void print_verilog_module_end(std::fstream& fp, std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type, const BasicPort& port_info, - const bool& must_print_port_size = true); + const bool& must_print_port_size = true, + const bool& big_endian = true); bool two_verilog_ports_mergeable(const BasicPort& portA, const BasicPort& portB); From b78e58d9bfcefff7574c572f52d33085156e7de2 Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Feb 2022 23:07:18 -0800 Subject: [PATCH 2/5] [Doc] Update doc about big endian syntax in bus group file format --- docs/source/manual/file_formats/bus_group_file.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/source/manual/file_formats/bus_group_file.rst b/docs/source/manual/file_formats/bus_group_file.rst index bf14fec4e..8faf0ffb7 100644 --- a/docs/source/manual/file_formats/bus_group_file.rst +++ b/docs/source/manual/file_formats/bus_group_file.rst @@ -13,7 +13,7 @@ An example of file is shown as follows. .. code-block:: xml - + @@ -28,6 +28,10 @@ Bus-related Syntax The bus port defined before synthesis, e.g., addr[0:3] +.. option:: big_endian="" + + Specify if this port should follow big endian or little endian in Verilog netlist. By default, big endian is assumed, e.g., addr[0:3]. + Pin-related Syntax ------------------ From 7645d5332d761d9e6c711ab2f7615a04bfd5914f Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 18 Feb 2022 23:09:03 -0800 Subject: [PATCH 3/5] [Test] Update bug group examples on the big endian support --- .../config/counter8_bus_group.xml | 18 +++++++++--------- .../config/counter8_bus_group.xml | 18 +++++++++--------- .../config/counter8_bus_group.xml | 18 +++++++++--------- .../config/counter8_bus_group.xml | 18 +++++++++--------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_explicit_mapping/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_explicit_mapping/config/counter8_bus_group.xml index 51dccca71..a0fd22f77 100644 --- a/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_explicit_mapping/config/counter8_bus_group.xml +++ b/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_explicit_mapping/config/counter8_bus_group.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_implicit_mapping/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_implicit_mapping/config/counter8_bus_group.xml index 51dccca71..a0fd22f77 100644 --- a/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_implicit_mapping/config/counter8_bus_group.xml +++ b/openfpga_flow/tasks/basic_tests/bus_group/full_testbench_implicit_mapping/config/counter8_bus_group.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_explicit_mapping/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_explicit_mapping/config/counter8_bus_group.xml index 51dccca71..a0fd22f77 100644 --- a/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_explicit_mapping/config/counter8_bus_group.xml +++ b/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_explicit_mapping/config/counter8_bus_group.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + diff --git a/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_implicit_mapping/config/counter8_bus_group.xml b/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_implicit_mapping/config/counter8_bus_group.xml index 51dccca71..a0fd22f77 100644 --- a/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_implicit_mapping/config/counter8_bus_group.xml +++ b/openfpga_flow/tasks/basic_tests/bus_group/preconfig_testbench_implicit_mapping/config/counter8_bus_group.xml @@ -1,12 +1,12 @@ - - - - - - - - - + + + + + + + + + From 3e43a60fdc0c8f31512eff12ae9cea411c8a6a5d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 19 Feb 2022 09:15:38 -0800 Subject: [PATCH 4/5] [FPGA-Verilog] Add big/little endian support when instanciate reference benchmarks --- openfpga/src/fpga_verilog/verilog_testbench_utils.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 4d19b5e96..4e1b3b1cf 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -156,8 +156,12 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (bus_id) { fp << "{"; int pin_counter = 0; - /* Include all the pins */ - for (const BusPinId& pin : bus_group.bus_pins(bus_id)) { + /* Include all the pins: If it follows little endian, reverse the pin sequence */ + std::vector bus_pins = bus_group.bus_pins(bus_id); + if (!bus_group.is_big_endian(bus_id)) { + std::reverse(bus_pins.begin(), bus_pins.end()); + } + for (const BusPinId& pin : bus_pins) { if (0 < pin_counter) { fp << ", "; } From 1c18d14ad5757d13e70b69daaee382672ff55e9d Mon Sep 17 00:00:00 2001 From: tangxifan Date: Sat, 19 Feb 2022 09:23:48 -0800 Subject: [PATCH 5/5] [FPGA-Verilog] Add big/little endian support to output ports --- openfpga/src/fpga_verilog/verilog_testbench_utils.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index 4e1b3b1cf..e566c8fb7 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -212,11 +212,16 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, /* For bus ports, include a complete list of pins */ BusGroupId bus_id = bus_group.find_bus(port_names[iport]); + if (bus_id) { fp << "{"; int pin_counter = 0; - /* Include all the pins */ - for (const BusPinId& pin : bus_group.bus_pins(bus_id)) { + /* Include all the pins: If it follows little endian, reverse the pin sequence */ + std::vector bus_pins = bus_group.bus_pins(bus_id); + if (!bus_group.is_big_endian(bus_id)) { + std::reverse(bus_pins.begin(), bus_pins.end()); + } + for (const BusPinId& pin : bus_pins) { if (0 < pin_counter) { fp << ", "; }