[FPGA-Verilog] Now instance can output bus ports with all the pins
This commit is contained in:
parent
aa375fd7a4
commit
0d620888ab
|
@ -59,6 +59,16 @@ BusGroupId BusGroup::find_pin_bus(const std::string& pin_name) const {
|
||||||
return pin_parent_bus_ids_[pin_id];
|
return pin_parent_bus_ids_[pin_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BusGroupId BusGroup::find_bus(const std::string& bus_name) const {
|
||||||
|
std::map<std::string, BusGroupId>::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 {
|
BusPinId BusGroup::find_pin(const std::string& pin_name) const {
|
||||||
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
std::map<std::string, BusPinId>::const_iterator result = pin_name2id_map_.find(pin_name);
|
||||||
if (result == pin_name2id_map_.end()) {
|
if (result == pin_name2id_map_.end()) {
|
||||||
|
@ -97,30 +107,40 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
|
||||||
bus_ports_.push_back(bus_port);
|
bus_ports_.push_back(bus_port);
|
||||||
bus_pin_ids_.emplace_back();
|
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;
|
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 */
|
/* Create a new id */
|
||||||
BusPinId pin_id = BusPinId(pin_ids_.size());
|
BusPinId pin_id = BusPinId(pin_ids_.size());
|
||||||
|
|
||||||
pin_ids_.push_back(pin_id);
|
pin_ids_.push_back(pin_id);
|
||||||
|
|
||||||
pin_indices_.emplace_back();
|
pin_indices_.push_back(index);
|
||||||
pin_names_.emplace_back();
|
pin_names_.emplace_back();
|
||||||
|
|
||||||
/* Register the pin to the bus */
|
/* Register the pin to the bus */
|
||||||
VTR_ASSERT(valid_bus_id(bus_id));
|
VTR_ASSERT(valid_bus_id(bus_id));
|
||||||
pin_parent_bus_ids_.push_back(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;
|
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) {
|
void BusGroup::set_pin_name(const BusPinId& pin_id, const std::string& name) {
|
||||||
VTR_ASSERT(valid_pin_id(pin_id));
|
VTR_ASSERT(valid_pin_id(pin_id));
|
||||||
|
|
|
@ -62,6 +62,9 @@ class BusGroup {
|
||||||
/* Find the bus that a pin belongs to */
|
/* Find the bus that a pin belongs to */
|
||||||
BusGroupId find_pin_bus(const std::string& pin_name) const;
|
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 */
|
/* Find the pin id with a given name */
|
||||||
BusPinId find_pin(const std::string& pin_name) const;
|
BusPinId find_pin(const std::string& pin_name) const;
|
||||||
|
|
||||||
|
@ -78,11 +81,8 @@ class BusGroup {
|
||||||
/* Add a bus to storage */
|
/* Add a bus to storage */
|
||||||
BusGroupId create_bus(const openfpga::BasicPort& bus_port);
|
BusGroupId create_bus(const openfpga::BasicPort& bus_port);
|
||||||
|
|
||||||
/* Add a pin to a bus */
|
/* 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);
|
BusPinId create_pin(const BusGroupId& bus_id, const int& index);
|
||||||
|
|
||||||
/* Set the index for a pin */
|
|
||||||
void set_pin_index(const BusPinId& pin_id, const int& index);
|
|
||||||
|
|
||||||
/* Set the name for a pin */
|
/* Set the name for a pin */
|
||||||
void set_pin_name(const BusPinId& pin_id, const std::string& name);
|
void set_pin_name(const BusPinId& pin_id, const std::string& name);
|
||||||
|
@ -117,6 +117,7 @@ class BusGroup {
|
||||||
vtr::vector<BusPinId, BusGroupId> pin_parent_bus_ids_;
|
vtr::vector<BusPinId, BusGroupId> pin_parent_bus_ids_;
|
||||||
|
|
||||||
/* Fast look-up */
|
/* Fast look-up */
|
||||||
|
std::map<std::string, BusGroupId> bus_name2id_map_;
|
||||||
std::map<std::string, BusPinId> pin_name2id_map_;
|
std::map<std::string, BusPinId> pin_name2id_map_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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");
|
"Pin index is out of range of the bus port width!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
BusPinId pin_id = bus_group.create_pin(bus_id);
|
BusPinId pin_id = bus_group.create_pin(bus_id, pin_index);
|
||||||
bus_group.set_pin_index(pin_id, pin_index);
|
|
||||||
bus_group.set_pin_name(pin_id, pin_name);
|
bus_group.set_pin_name(pin_id, pin_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
||||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print out the instance with port mapping */
|
||||||
size_t port_counter = 0;
|
size_t port_counter = 0;
|
||||||
for (size_t iport = 0; iport < port_names.size(); ++iport) {
|
for (size_t iport = 0; iport < port_names.size(); ++iport) {
|
||||||
/* The first port does not need a comma */
|
/* 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) {
|
if (true == use_explicit_port_map) {
|
||||||
fp << "." << port_names[iport] << module_input_port_postfix << "(";
|
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 */
|
/* For bus ports, include a complete list of pins */
|
||||||
if (clock_port_names.end() != std::find(clock_port_names.begin(), clock_port_names.end(), port_names[iport])) {
|
BusGroupId bus_id = bus_group.find_bus(port_names[iport]);
|
||||||
fp << 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 {
|
} 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) {
|
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) {
|
if (true == use_explicit_port_map) {
|
||||||
fp << "." << output_block_name << module_output_port_postfix << "(";
|
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) {
|
if (true == use_explicit_port_map) {
|
||||||
fp << ")";
|
fp << ")";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue