diff --git a/libopenfpga/libbusgroup/src/bus_group.cpp b/libopenfpga/libbusgroup/src/bus_group.cpp index 71a433793..9e191c12f 100644 --- a/libopenfpga/libbusgroup/src/bus_group.cpp +++ b/libopenfpga/libbusgroup/src/bus_group.cpp @@ -59,6 +59,16 @@ BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const { return pin_parent_bus_ids_[pin_id]; } +BusGroupId BusGroup::find_bus(const std::string& bus_name) const { + std::map::const_iterator result = bus_name2id_map_.find(bus_name); + if (result == bus_name2id_map_.end()) { + /* Not found, return an invalid id */ + return BusGroupId::INVALID(); + } + /* Found, we should get the parent bus */ + return result->second; +} + BusPinId BusGroup::find_pin(const std::string& pin_name) const { std::map::const_iterator result = pin_name2id_map_.find(pin_name); if (result == pin_name2id_map_.end()) { @@ -96,31 +106,41 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) { bus_ids_.push_back(bus_id); bus_ports_.push_back(bus_port); bus_pin_ids_.emplace_back(); + + /* Register to fast look-up */ + auto result = bus_name2id_map_.find(bus_port.get_name()); + if (result == bus_name2id_map_.end()) { + bus_name2id_map_[bus_port.get_name()] = bus_id; + } else { + VTR_LOG_ERROR("Duplicated bus name '%s' in bus group", bus_port.get_name().c_str()); + exit(1); + } return bus_id; } -BusPinId BusGroup::create_pin(const BusGroupId& bus_id) { +BusPinId BusGroup::create_pin(const BusGroupId& bus_id, const int& index) { /* Create a new id */ BusPinId pin_id = BusPinId(pin_ids_.size()); pin_ids_.push_back(pin_id); - pin_indices_.emplace_back(); + pin_indices_.push_back(index); pin_names_.emplace_back(); /* Register the pin to the bus */ VTR_ASSERT(valid_bus_id(bus_id)); pin_parent_bus_ids_.push_back(bus_id); - bus_pin_ids_[bus_id].push_back(pin_id); + + /* If the pin index is beyond the range of the bus_pin_ids, resize it */ + if (size_t(index) > bus_pin_ids_[bus_id].size()) { + bus_pin_ids_[bus_id].resize(index + 1); + } + bus_pin_ids_[bus_id][index] = pin_id; return pin_id; } -void BusGroup::set_pin_index(const BusPinId& pin_id, const int& index) { - VTR_ASSERT(valid_pin_id(pin_id)); - pin_indices_[pin_id] = index; -} void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) { VTR_ASSERT(valid_pin_id(pin_id)); diff --git a/libopenfpga/libbusgroup/src/bus_group.h b/libopenfpga/libbusgroup/src/bus_group.h index d849f5fd3..da63fb210 100644 --- a/libopenfpga/libbusgroup/src/bus_group.h +++ b/libopenfpga/libbusgroup/src/bus_group.h @@ -62,6 +62,9 @@ class BusGroup { /* Find the bus that a pin belongs to */ BusGroupId find_pin_bus(const std::string& pin_name) const; + /* Find the bus id with a given name */ + BusGroupId find_bus(const std::string& bus_name) const; + /* Find the pin id with a given name */ BusPinId find_pin(const std::string& pin_name) const; @@ -78,11 +81,8 @@ class BusGroup { /* Add a bus to storage */ BusGroupId create_bus(const openfpga::BasicPort& bus_port); - /* Add a pin to a bus */ - BusPinId create_pin(const BusGroupId& bus_id); - - /* Set the index for a pin */ - void set_pin_index(const BusPinId& pin_id, const int& index); + /* 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); /* Set the name for a pin */ void set_pin_name(const BusPinId& pin_id, const std::string& name); @@ -117,6 +117,7 @@ class BusGroup { vtr::vector pin_parent_bus_ids_; /* Fast look-up */ + std::map bus_name2id_map_; std::map pin_name2id_map_; }; diff --git a/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp index 701cbb1bf..020aa224b 100644 --- a/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp +++ b/libopenfpga/libbusgroup/src/read_xml_bus_group.cpp @@ -48,8 +48,7 @@ void read_xml_pin(pugi::xml_node& xml_pin, "Pin index is out of range of the bus port width!\n"); } - BusPinId pin_id = bus_group.create_pin(bus_id); - bus_group.set_pin_index(pin_id, pin_index); + BusPinId pin_id = bus_group.create_pin(bus_id, pin_index); bus_group.set_pin_name(pin_id, pin_name); } diff --git a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp index f1799796a..c1c379366 100644 --- a/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp +++ b/openfpga/src/fpga_verilog/verilog_testbench_utils.cpp @@ -130,6 +130,7 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, port_types.push_back(atom_ctx.nlist.block_type(atom_blk)); } + /* Print out the instance with port mapping */ size_t port_counter = 0; for (size_t iport = 0; iport < port_names.size(); ++iport) { /* The first port does not need a comma */ @@ -142,20 +143,51 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (true == use_explicit_port_map) { fp << "." << port_names[iport] << module_input_port_postfix << "("; } - /* Polarity of some input may have to be inverted, as defined in pin constraints - * For example, the reset signal of the benchmark is active low - * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) - * However, to ensure correct stimuli to the benchmark, we have to invert the signal - */ - if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(port_names[iport])) { - fp << "~"; - } - /* For clock ports, skip postfix */ - if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) { - fp << port_names[iport]; + /* 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)) { + if (0 < pin_counter) { + fp << ", "; + } + /* Polarity of some input may have to be inverted, as defined in pin constraints + * For example, the reset signal of the benchmark is active low + * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) + * However, to ensure correct stimuli to the benchmark, we have to invert the signal + */ + if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(bus_group.pin_name(pin))) { + fp << "~"; + } + + fp << bus_group.pin_name(pin); + + /* For clock ports, skip postfix */ + if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) { + fp << input_port_postfix; + } + + pin_counter++; + } + fp << "}"; } else { - fp << port_names[iport] << input_port_postfix; + /* Polarity of some input may have to be inverted, as defined in pin constraints + * For example, the reset signal of the benchmark is active low + * while the reset signal of the FPGA fabric is active high (inside FPGA, the reset signal will be inverted) + * However, to ensure correct stimuli to the benchmark, we have to invert the signal + */ + if (PinConstraints::LOGIC_HIGH == pin_constraints.net_default_value(port_names[iport])) { + fp << "~"; + } + + fp << port_names[iport]; + /* For clock ports, skip postfix */ + if (clock_port_names.end() == std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) { + fp << input_port_postfix; + } } if (true == use_explicit_port_map) { @@ -179,7 +211,24 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp, if (true == use_explicit_port_map) { fp << "." << output_block_name << module_output_port_postfix << "("; } - fp << port_names[iport] << output_port_postfix; + + /* 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)) { + if (0 < pin_counter) { + fp << ", "; + } + fp << bus_group.pin_name(pin) << output_port_postfix; + pin_counter++; + } + fp << "}"; + } else { + fp << port_names[iport] << output_port_postfix; + } if (true == use_explicit_port_map) { fp << ")"; }