Merge pull request #540 from lnis-uofu/bus_support
Bus support now support big-endian and little-endian
This commit is contained in:
commit
756c340232
|
@ -13,7 +13,7 @@ An example of file is shown as follows.
|
||||||
.. code-block:: xml
|
.. code-block:: xml
|
||||||
|
|
||||||
<bus_group>
|
<bus_group>
|
||||||
<bus name="i_addr[0:3]">
|
<bus name="i_addr[0:3]" big_endian="false">
|
||||||
<pin id="0" name="i_addr_0_"/>
|
<pin id="0" name="i_addr_0_"/>
|
||||||
<pin id="1" name="i_addr_1_"/>
|
<pin id="1" name="i_addr_1_"/>
|
||||||
<pin id="2" name="i_addr_2_"/>
|
<pin id="2" name="i_addr_2_"/>
|
||||||
|
@ -28,6 +28,10 @@ Bus-related Syntax
|
||||||
|
|
||||||
The bus port defined before synthesis, e.g., addr[0:3]
|
The bus port defined before synthesis, e.g., addr[0:3]
|
||||||
|
|
||||||
|
.. option:: big_endian="<bool>"
|
||||||
|
|
||||||
|
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
|
Pin-related Syntax
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,11 @@ openfpga::BasicPort BusGroup::bus_port(const BusGroupId& bus_id) const {
|
||||||
return bus_ports_[bus_id];
|
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<BusPinId> BusGroup::bus_pins(const BusGroupId& bus_id) const {
|
std::vector<BusPinId> BusGroup::bus_pins(const BusGroupId& bus_id) const {
|
||||||
VTR_ASSERT(valid_bus_id(bus_id));
|
VTR_ASSERT(valid_bus_id(bus_id));
|
||||||
return bus_pin_ids_[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) {
|
void BusGroup::reserve_buses(const size_t& num_buses) {
|
||||||
bus_ids_.reserve(num_buses);
|
bus_ids_.reserve(num_buses);
|
||||||
bus_ports_.reserve(num_buses);
|
bus_ports_.reserve(num_buses);
|
||||||
|
bus_big_endians_.reserve(num_buses);
|
||||||
bus_pin_ids_.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_ids_.push_back(bus_id);
|
||||||
bus_ports_.push_back(bus_port);
|
bus_ports_.push_back(bus_port);
|
||||||
|
bus_big_endians_.push_back(true);
|
||||||
bus_pin_ids_.emplace_back();
|
bus_pin_ids_.emplace_back();
|
||||||
|
|
||||||
/* Register to fast look-up */
|
/* Register to fast look-up */
|
||||||
|
@ -119,6 +126,11 @@ BusGroupId BusGroup::create_bus(const openfpga::BasicPort& bus_port) {
|
||||||
return bus_id;
|
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) {
|
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());
|
||||||
|
|
|
@ -50,6 +50,9 @@ class BusGroup {
|
||||||
/** Get port information of a bus with a given id */
|
/** Get port information of a bus with a given id */
|
||||||
BasicPort bus_port(const BusGroupId& bus_id) const;
|
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 */
|
/* Get the pins under a specific bus */
|
||||||
std::vector<BusPinId> bus_pins(const BusGroupId& bus_id) const;
|
std::vector<BusPinId> bus_pins(const BusGroupId& bus_id) const;
|
||||||
|
|
||||||
|
@ -81,6 +84,9 @@ 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);
|
||||||
|
|
||||||
|
/* 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] */
|
/* 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);
|
BusPinId create_pin(const BusGroupId& bus_id, const int& index);
|
||||||
|
|
||||||
|
@ -101,6 +107,9 @@ class BusGroup {
|
||||||
/* Port information of each bus */
|
/* Port information of each bus */
|
||||||
vtr::vector<BusGroupId, BasicPort> bus_ports_;
|
vtr::vector<BusGroupId, BasicPort> bus_ports_;
|
||||||
|
|
||||||
|
/* Endianness of each bus: big endian by default */
|
||||||
|
vtr::vector<BusGroupId, bool> bus_big_endians_;
|
||||||
|
|
||||||
/* Indices of each pin under each bus */
|
/* Indices of each pin under each bus */
|
||||||
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
|
vtr::vector<BusGroupId, std::vector<BusPinId>> bus_pin_ids_;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
constexpr char* XML_BUS_GROUP_NODE_NAME = "bus_group";
|
constexpr char* XML_BUS_GROUP_NODE_NAME = "bus_group";
|
||||||
constexpr char* XML_BUS_NODE_NAME = "bus";
|
constexpr char* XML_BUS_NODE_NAME = "bus";
|
||||||
constexpr char* XML_BUS_PORT_ATTRIBUTE_NAME = "name";
|
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_NODE_NAME = "pin";
|
||||||
constexpr char* XML_PIN_INDEX_ATTRIBUTE_NAME = "id";
|
constexpr char* XML_PIN_INDEX_ATTRIBUTE_NAME = "id";
|
||||||
constexpr char* XML_PIN_NAME_ATTRIBUTE_NAME = "name";
|
constexpr char* XML_PIN_NAME_ATTRIBUTE_NAME = "name";
|
||||||
|
|
|
@ -76,6 +76,9 @@ void read_xml_bus(pugi::xml_node& xml_bus,
|
||||||
"Bus port is invalid, check LSB and MSB!\n");
|
"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()) {
|
for (pugi::xml_node xml_pin : xml_bus.children()) {
|
||||||
/* Error out if the XML child has an invalid name! */
|
/* Error out if the XML child has an invalid name! */
|
||||||
if (xml_pin.name() != std::string(XML_PIN_NODE_NAME)) {
|
if (xml_pin.name() != std::string(XML_PIN_NODE_NAME)) {
|
||||||
|
|
|
@ -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_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";
|
fp << ">" << "\n";
|
||||||
|
|
||||||
/* Output all the pins under this bus */
|
/* Output all the pins under this bus */
|
||||||
|
|
|
@ -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 */
|
/* Ports to be added, this is to avoid any bus port */
|
||||||
std::vector<BasicPort> port_list;
|
std::vector<BasicPort> port_list;
|
||||||
std::vector<AtomBlockType> port_types;
|
std::vector<AtomBlockType> port_types;
|
||||||
|
std::vector<bool> port_big_endian;
|
||||||
|
|
||||||
/* Print all the I/Os of the circuit implementation to be tested*/
|
/* Print all the I/Os of the circuit implementation to be tested*/
|
||||||
for (const AtomBlockId &atom_blk : atom_ctx.nlist.blocks()) {
|
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))) {
|
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_list.push_back(bus_group.bus_port(bus_id));
|
||||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
||||||
|
port_big_endian.push_back(bus_group.is_big_endian(bus_id));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -104,6 +106,7 @@ void print_verilog_preconfig_top_module_ports(std::fstream &fp,
|
||||||
BasicPort module_port(std::string(block_name), 1);
|
BasicPort module_port(std::string(block_name), 1);
|
||||||
port_list.push_back(module_port);
|
port_list.push_back(module_port);
|
||||||
port_types.push_back(atom_ctx.nlist.block_type(atom_blk));
|
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 */
|
/* 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 << "," << 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 */
|
/* Update port counter */
|
||||||
port_counter++;
|
port_counter++;
|
||||||
|
|
|
@ -156,8 +156,12 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
||||||
if (bus_id) {
|
if (bus_id) {
|
||||||
fp << "{";
|
fp << "{";
|
||||||
int pin_counter = 0;
|
int pin_counter = 0;
|
||||||
/* Include all the pins */
|
/* Include all the pins: If it follows little endian, reverse the pin sequence */
|
||||||
for (const BusPinId& pin : bus_group.bus_pins(bus_id)) {
|
std::vector<BusPinId> 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) {
|
if (0 < pin_counter) {
|
||||||
fp << ", ";
|
fp << ", ";
|
||||||
}
|
}
|
||||||
|
@ -208,11 +212,16 @@ void print_verilog_testbench_benchmark_instance(std::fstream& fp,
|
||||||
|
|
||||||
/* For bus ports, include a complete list of pins */
|
/* For bus ports, include a complete list of pins */
|
||||||
BusGroupId bus_id = bus_group.find_bus(port_names[iport]);
|
BusGroupId bus_id = bus_group.find_bus(port_names[iport]);
|
||||||
|
|
||||||
if (bus_id) {
|
if (bus_id) {
|
||||||
fp << "{";
|
fp << "{";
|
||||||
int pin_counter = 0;
|
int pin_counter = 0;
|
||||||
/* Include all the pins */
|
/* Include all the pins: If it follows little endian, reverse the pin sequence */
|
||||||
for (const BusPinId& pin : bus_group.bus_pins(bus_id)) {
|
std::vector<BusPinId> 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) {
|
if (0 < pin_counter) {
|
||||||
fp << ", ";
|
fp << ", ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
std::string generate_verilog_port(const enum e_dump_verilog_port_type& verilog_port_type,
|
||||||
const BasicPort& port_info,
|
const BasicPort& port_info,
|
||||||
const bool& must_print_port_size) {
|
const bool& must_print_port_size,
|
||||||
|
const bool& big_endian) {
|
||||||
std::string verilog_line;
|
std::string verilog_line;
|
||||||
|
|
||||||
/* Ensure the port type is valid */
|
/* Ensure the port type is valid */
|
||||||
VTR_ASSERT(verilog_port_type < NUM_VERILOG_PORT_TYPES);
|
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 <port_name>[<lsb>:<msb>]
|
/* Only connection require a format of <port_name>[<lsb>:<msb>]
|
||||||
* others require a format of <port_type> [<lsb>:<msb>] <port_name>
|
* others require a format of <port_type> [<lsb>:<msb>] <port_name>
|
||||||
|
|
|
@ -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,
|
std::string generate_verilog_port(const enum e_dump_verilog_port_type& dump_port_type,
|
||||||
const BasicPort& port_info,
|
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,
|
bool two_verilog_ports_mergeable(const BasicPort& portA,
|
||||||
const BasicPort& portB);
|
const BasicPort& portB);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<bus_group>
|
<bus_group>
|
||||||
<bus name="result[0:7]">
|
<bus name="result[7:0]" big_endian="false">
|
||||||
<pin id="0" name="result_7_"/>
|
<pin id="0" name="result_0_"/>
|
||||||
<pin id="1" name="result_6_"/>
|
<pin id="1" name="result_1_"/>
|
||||||
<pin id="2" name="result_5_"/>
|
<pin id="2" name="result_2_"/>
|
||||||
<pin id="3" name="result_4_"/>
|
<pin id="3" name="result_3_"/>
|
||||||
<pin id="4" name="result_3_"/>
|
<pin id="4" name="result_4_"/>
|
||||||
<pin id="5" name="result_2_"/>
|
<pin id="5" name="result_5_"/>
|
||||||
<pin id="6" name="result_1_"/>
|
<pin id="6" name="result_6_"/>
|
||||||
<pin id="7" name="result_0_"/>
|
<pin id="7" name="result_7_"/>
|
||||||
</bus>
|
</bus>
|
||||||
</bus_group>
|
</bus_group>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<bus_group>
|
<bus_group>
|
||||||
<bus name="result[0:7]">
|
<bus name="result[7:0]" big_endian="false">
|
||||||
<pin id="0" name="result_7_"/>
|
<pin id="0" name="result_0_"/>
|
||||||
<pin id="1" name="result_6_"/>
|
<pin id="1" name="result_1_"/>
|
||||||
<pin id="2" name="result_5_"/>
|
<pin id="2" name="result_2_"/>
|
||||||
<pin id="3" name="result_4_"/>
|
<pin id="3" name="result_3_"/>
|
||||||
<pin id="4" name="result_3_"/>
|
<pin id="4" name="result_4_"/>
|
||||||
<pin id="5" name="result_2_"/>
|
<pin id="5" name="result_5_"/>
|
||||||
<pin id="6" name="result_1_"/>
|
<pin id="6" name="result_6_"/>
|
||||||
<pin id="7" name="result_0_"/>
|
<pin id="7" name="result_7_"/>
|
||||||
</bus>
|
</bus>
|
||||||
</bus_group>
|
</bus_group>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<bus_group>
|
<bus_group>
|
||||||
<bus name="result[0:7]">
|
<bus name="result[7:0]" big_endian="false">
|
||||||
<pin id="0" name="result_7_"/>
|
<pin id="0" name="result_0_"/>
|
||||||
<pin id="1" name="result_6_"/>
|
<pin id="1" name="result_1_"/>
|
||||||
<pin id="2" name="result_5_"/>
|
<pin id="2" name="result_2_"/>
|
||||||
<pin id="3" name="result_4_"/>
|
<pin id="3" name="result_3_"/>
|
||||||
<pin id="4" name="result_3_"/>
|
<pin id="4" name="result_4_"/>
|
||||||
<pin id="5" name="result_2_"/>
|
<pin id="5" name="result_5_"/>
|
||||||
<pin id="6" name="result_1_"/>
|
<pin id="6" name="result_6_"/>
|
||||||
<pin id="7" name="result_0_"/>
|
<pin id="7" name="result_7_"/>
|
||||||
</bus>
|
</bus>
|
||||||
</bus_group>
|
</bus_group>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<bus_group>
|
<bus_group>
|
||||||
<bus name="result[0:7]">
|
<bus name="result[7:0]" big_endian="false">
|
||||||
<pin id="0" name="result_7_"/>
|
<pin id="0" name="result_0_"/>
|
||||||
<pin id="1" name="result_6_"/>
|
<pin id="1" name="result_1_"/>
|
||||||
<pin id="2" name="result_5_"/>
|
<pin id="2" name="result_2_"/>
|
||||||
<pin id="3" name="result_4_"/>
|
<pin id="3" name="result_3_"/>
|
||||||
<pin id="4" name="result_3_"/>
|
<pin id="4" name="result_4_"/>
|
||||||
<pin id="5" name="result_2_"/>
|
<pin id="5" name="result_5_"/>
|
||||||
<pin id="6" name="result_1_"/>
|
<pin id="6" name="result_6_"/>
|
||||||
<pin id="7" name="result_0_"/>
|
<pin id="7" name="result_7_"/>
|
||||||
</bus>
|
</bus>
|
||||||
</bus_group>
|
</bus_group>
|
||||||
|
|
Loading…
Reference in New Issue