From f081cef495b74f29830cc897b1e929b04a29ad1b Mon Sep 17 00:00:00 2001 From: tangxifan Date: Fri, 12 Jun 2020 00:07:04 -0600 Subject: [PATCH] add fabric key library --- libopenfpga/CMakeLists.txt | 1 + .../libarchopenfpga/src/write_xml_utils.cpp | 15 ++++ .../libarchopenfpga/src/write_xml_utils.h | 4 + libopenfpga/libfabrickey/CMakeLists.txt | 35 ++++++++ .../libfabrickey/key_examples/key_example.xml | 7 ++ libopenfpga/libfabrickey/src/fabric_key.cpp | 82 +++++++++++++++++ libopenfpga/libfabrickey/src/fabric_key.h | 59 +++++++++++++ libopenfpga/libfabrickey/src/fabric_key_fwd.h | 22 +++++ .../libfabrickey/src/read_xml_fabric_key.cpp | 88 +++++++++++++++++++ .../libfabrickey/src/read_xml_fabric_key.h | 16 ++++ .../libfabrickey/src/write_xml_fabric_key.cpp | 69 +++++++++++++++ .../libfabrickey/src/write_xml_fabric_key.h | 16 ++++ .../libfabrickey/test/test_fabric_key.cpp | 34 +++++++ 13 files changed, 448 insertions(+) create mode 100644 libopenfpga/libfabrickey/CMakeLists.txt create mode 100644 libopenfpga/libfabrickey/key_examples/key_example.xml create mode 100644 libopenfpga/libfabrickey/src/fabric_key.cpp create mode 100644 libopenfpga/libfabrickey/src/fabric_key.h create mode 100644 libopenfpga/libfabrickey/src/fabric_key_fwd.h create mode 100644 libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp create mode 100644 libopenfpga/libfabrickey/src/read_xml_fabric_key.h create mode 100644 libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp create mode 100644 libopenfpga/libfabrickey/src/write_xml_fabric_key.h create mode 100644 libopenfpga/libfabrickey/test/test_fabric_key.cpp diff --git a/libopenfpga/CMakeLists.txt b/libopenfpga/CMakeLists.txt index 00cf0acf0..ec3299198 100644 --- a/libopenfpga/CMakeLists.txt +++ b/libopenfpga/CMakeLists.txt @@ -3,3 +3,4 @@ add_subdirectory(libini) add_subdirectory(libopenfpgashell) add_subdirectory(libarchopenfpga) add_subdirectory(libopenfpgautil) +add_subdirectory(libfabrickey) diff --git a/libopenfpga/libarchopenfpga/src/write_xml_utils.cpp b/libopenfpga/libarchopenfpga/src/write_xml_utils.cpp index e4d32e720..a416203ee 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_utils.cpp +++ b/libopenfpga/libarchopenfpga/src/write_xml_utils.cpp @@ -61,6 +61,21 @@ void write_xml_attribute(std::fstream& fp, fp << "\""; } +/******************************************************************** + * A most utilized function to write an XML attribute to file + * This accepts the value as a size_t + *******************************************************************/ +void write_xml_attribute(std::fstream& fp, + const char* attr, + const size_t& value) { + /* Validate the file stream */ + openfpga::valid_file_stream(fp); + + fp << " " << attr << "=\""; + fp << value; + fp << "\""; +} + /******************************************************************** * A most utilized function to write an XML attribute to file * This accepts the value as a float diff --git a/libopenfpga/libarchopenfpga/src/write_xml_utils.h b/libopenfpga/libarchopenfpga/src/write_xml_utils.h index 3976d78b9..b54caf6db 100644 --- a/libopenfpga/libarchopenfpga/src/write_xml_utils.h +++ b/libopenfpga/libarchopenfpga/src/write_xml_utils.h @@ -26,4 +26,8 @@ void write_xml_attribute(std::fstream& fp, const char* attr, const float& value); +void write_xml_attribute(std::fstream& fp, + const char* attr, + const size_t& value); + #endif diff --git a/libopenfpga/libfabrickey/CMakeLists.txt b/libopenfpga/libfabrickey/CMakeLists.txt new file mode 100644 index 000000000..db52b510e --- /dev/null +++ b/libopenfpga/libfabrickey/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.9) + +project("libfabrickey") + +file(GLOB_RECURSE EXEC_SOURCES test/*.cpp) +file(GLOB_RECURSE LIB_SOURCES src/*.cpp) +file(GLOB_RECURSE LIB_HEADERS src/*.h) +files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS) + +#Remove test executable from library +list(REMOVE_ITEM LIB_SOURCES ${EXEC_SOURCES}) + +#Create the library +add_library(libfabrickey STATIC + ${LIB_HEADERS} + ${LIB_SOURCES}) +target_include_directories(libfabrickey PUBLIC ${LIB_INCLUDE_DIRS}) +set_target_properties(libfabrickey PROPERTIES PREFIX "") #Avoid extra 'lib' prefix + +#Specify link-time dependancies +target_link_libraries(libfabrickey + libopenfpgautil + libarchopenfpga + libvtrutil + libpugixml + libpugiutil) + +#Create the test executable +foreach(testsourcefile ${EXEC_SOURCES}) + # Use a simple string replace, to cut off .cpp. + get_filename_component(testname ${testsourcefile} NAME_WE) + add_executable(${testname} ${testsourcefile}) + # Make sure the library is linked to each test executable + target_link_libraries(${testname} libfabrickey) +endforeach(testsourcefile ${EXEC_SOURCES}) diff --git a/libopenfpga/libfabrickey/key_examples/key_example.xml b/libopenfpga/libfabrickey/key_examples/key_example.xml new file mode 100644 index 000000000..49140b6e0 --- /dev/null +++ b/libopenfpga/libfabrickey/key_examples/key_example.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/libopenfpga/libfabrickey/src/fabric_key.cpp b/libopenfpga/libfabrickey/src/fabric_key.cpp new file mode 100644 index 000000000..187150800 --- /dev/null +++ b/libopenfpga/libfabrickey/src/fabric_key.cpp @@ -0,0 +1,82 @@ +#include "vtr_assert.h" + +#include "fabric_key.h" + +/************************************************************************ + * Member functions for class FabricKey + ***********************************************************************/ + +/************************************************************************ + * Constructors + ***********************************************************************/ +FabricKey::FabricKey() { + return; +} + +/************************************************************************ + * Public Accessors : aggregates + ***********************************************************************/ +FabricKey::fabric_key_range FabricKey::keys() const { + return vtr::make_range(key_ids_.begin(), key_ids_.end()); +} + +/************************************************************************ + * Public Accessors : Basic data query + ***********************************************************************/ +/* Access the name of a key */ +std::string FabricKey::key_name(const FabricKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + return key_names_[key_id]; +} + +/* Access the value of a key */ +size_t FabricKey::key_value(const FabricKeyId& key_id) const { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + return key_values_[key_id]; +} + +/************************************************************************ + * Public Mutators + ***********************************************************************/ +void FabricKey::reserve_keys(const size_t& num_keys) { + key_ids_.reserve(num_keys); + key_names_.reserve(num_keys); + key_values_.reserve(num_keys); +} + +/* Create a new key and add it to the library, return an id */ +FabricKeyId FabricKey::create_key() { + /* Create a new id */ + FabricKeyId key = FabricKeyId(key_ids_.size()); + key_ids_.push_back(key); + key_names_.emplace_back(); + key_values_.emplace_back(); + + return key; +} + +void FabricKey::set_key_name(const FabricKeyId& key_id, + const std::string& name) { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + + key_names_[key_id] = name; +} + +void FabricKey::set_key_value(const FabricKeyId& key_id, + const size_t& value) { + /* validate the key_id */ + VTR_ASSERT(valid_key_id(key_id)); + + key_values_[key_id] = value; +} + +/************************************************************************ + * Internal invalidators/validators + ***********************************************************************/ +/* Validators */ +bool FabricKey::valid_key_id(const FabricKeyId& key_id) const { + return ( size_t(key_id) < key_ids_.size() ) && ( key_id == key_ids_[key_id] ); +} diff --git a/libopenfpga/libfabrickey/src/fabric_key.h b/libopenfpga/libfabrickey/src/fabric_key.h new file mode 100644 index 000000000..7488923df --- /dev/null +++ b/libopenfpga/libfabrickey/src/fabric_key.h @@ -0,0 +1,59 @@ +#ifndef FABRIC_KEY_H +#define FABRIC_KEY_H + +/******************************************************************** + * This file include the declaration of fabric key + *******************************************************************/ +#include +#include +#include + +/* Headers from vtrutil library */ +#include "vtr_vector.h" + +#include "fabric_key_fwd.h" + +/******************************************************************** + * A data structure to describe a secure key for fabric organization + * + * Typical usage: + * -------------- + * // Create an empty fabric key + * FabricKey fabric_key; + * // Add a key with name and value + * FabricKeyId key = fabic_key.create_key(key_name, key_value); + * + *******************************************************************/ +class FabricKey { + public: /* Types */ + typedef vtr::vector::const_iterator fabric_key_iterator; + /* Create range */ + typedef vtr::Range fabric_key_range; + public: /* Constructors */ + FabricKey(); + public: /* Accessors: aggregates */ + fabric_key_range keys() const; + public: /* Public Accessors: Basic data query */ + std::string key_name(const FabricKeyId& key_id) const; + size_t key_value(const FabricKeyId& key_id) const; + public: /* Public Mutators: model-related */ + void reserve_keys(const size_t& num_keys); + FabricKeyId create_key(); + void set_key_name(const FabricKeyId& key_id, + const std::string& name); + void set_key_value(const FabricKeyId& key_id, + const size_t& value); + public: /* Public invalidators/validators */ + bool valid_key_id(const FabricKeyId& key_id) const; + private: /* Internal data */ + /* Unique ids for each key */ + vtr::vector key_ids_; + + /* Names for each key */ + vtr::vector key_names_; + + /* Values for each key */ + vtr::vector key_values_; +}; + +#endif diff --git a/libopenfpga/libfabrickey/src/fabric_key_fwd.h b/libopenfpga/libfabrickey/src/fabric_key_fwd.h new file mode 100644 index 000000000..523eaeab8 --- /dev/null +++ b/libopenfpga/libfabrickey/src/fabric_key_fwd.h @@ -0,0 +1,22 @@ +/************************************************************************ + * A header file for FabricKey class, including critical data declaration + * Please include this file only for using any TechnologyLibrary data structure + * Refer to fabric_key.h for more details + ***********************************************************************/ + +/************************************************************************ + * Create strong id for FabricKey to avoid illegal type casting + ***********************************************************************/ +#ifndef FABRIC_KEY_FWD_H +#define FABRIC_KEY_FWD_H + +#include "vtr_strong_id.h" + +struct fabric_key_id_tag; + +typedef vtr::StrongId FabricKeyId; + +/* Short declaration of class */ +class FabricKey; + +#endif diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp new file mode 100644 index 000000000..8b1f03f11 --- /dev/null +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.cpp @@ -0,0 +1,88 @@ +/******************************************************************** + * This file includes the top-level function of this library + * which reads an XML of a fabric key to the associated + * data structures + *******************************************************************/ +#include + +/* Headers from pugi XML library */ +#include "pugixml.hpp" +#include "pugixml_util.hpp" + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_time.h" + +/* Headers from libarchfpga */ +#include "arch_error.h" +#include "read_xml_util.h" + +#include "read_xml_fabric_key.h" + +/******************************************************************** + * Parse XML codes of a to an object of FabricKey + *******************************************************************/ +static +void read_xml_component_key(pugi::xml_node& xml_component_key, + const pugiutil::loc_data& loc_data, + FabricKey& fabric_key) { + + /* Find the id of component key */ + const size_t& id = get_attribute(xml_component_key, "id", loc_data).as_int(); + const std::string& name = get_attribute(xml_component_key, "name", loc_data).as_string(); + const size_t& value = get_attribute(xml_component_key, "value", loc_data).as_int(); + + if (false == fabric_key.valid_key_id(FabricKeyId(id))) { + archfpga_throw(loc_data.filename_c_str(), loc_data.line(xml_component_key), + "Invalid 'id' attribute '%d'\n", + id); + } + + VTR_ASSERT_SAFE(true == fabric_key.valid_key_id(FabricKeyId(id))); + + fabric_key.set_key_name(FabricKeyId(id), name); + fabric_key.set_key_value(FabricKeyId(id), value); +} + +/******************************************************************** + * Parse XML codes about to an object of FabricKey + *******************************************************************/ +FabricKey read_xml_fabric_key(const char* key_fname) { + + vtr::ScopedStartFinishTimer timer("Read Fabric Key"); + + FabricKey fabric_key; + + /* Parse the file */ + pugi::xml_document doc; + pugiutil::loc_data loc_data; + + try { + loc_data = pugiutil::load_xml(doc, key_fname); + + pugi::xml_node xml_root = get_single_child(doc, "fabric_key", loc_data); + + size_t num_keys = std::distance(xml_root.children().begin(), xml_root.children().end()); + fabric_key.reserve_keys(num_keys); + for (size_t ikey = 0; ikey < num_keys; ++ikey) { + fabric_key.create_key(); + } + + /* Iterate over the children under this node, + * each child should be named after circuit_model + */ + for (pugi::xml_node xml_key : xml_root.children()) { + /* Error out if the XML child has an invalid name! */ + if (xml_key.name() != std::string("key")) { + bad_tag(xml_key, loc_data, xml_root, {"key"}); + } + read_xml_component_key(xml_key, loc_data, fabric_key); + } + } catch (pugiutil::XmlError& e) { + archfpga_throw(key_fname, e.line(), + "%s", e.what()); + } + + return fabric_key; +} + diff --git a/libopenfpga/libfabrickey/src/read_xml_fabric_key.h b/libopenfpga/libfabrickey/src/read_xml_fabric_key.h new file mode 100644 index 000000000..692722d08 --- /dev/null +++ b/libopenfpga/libfabrickey/src/read_xml_fabric_key.h @@ -0,0 +1,16 @@ +#ifndef READ_XML_FABRIC_KEY_H +#define READ_XML_FABRIC_KEY_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include "pugixml_util.hpp" +#include "pugixml.hpp" +#include "fabric_key.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +FabricKey read_xml_fabric_key(const char* key_fname); + +#endif diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp new file mode 100644 index 000000000..d384d8607 --- /dev/null +++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.cpp @@ -0,0 +1,69 @@ +/******************************************************************** + * This file includes functions that outputs a configuration protocol to XML format + *******************************************************************/ +/* Headers from system goes first */ +#include +#include + +/* Headers from vtr util library */ +#include "vtr_assert.h" +#include "vtr_log.h" +#include "vtr_time.h" +#include "openfpga_digest.h" + +/* Headers from arch openfpga library */ +#include "write_xml_utils.h" + +/* Headers from fabrickey library */ +#include "write_xml_fabric_key.h" + +/******************************************************************** + * A writer to output a component key to XML format + *******************************************************************/ +static +void write_xml_fabric_component_key(std::fstream& fp, + const char* fname, + const FabricKey& fabric_key, + const FabricKeyId& component_key) { + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + fp << "\t" << "" << "\n"; +} + +/******************************************************************** + * A writer to output a fabric key to XML format + *******************************************************************/ +void write_xml_fabric_key(const char* fname, + const FabricKey& fabric_key) { + + vtr::ScopedStartFinishTimer timer("Write Fabric Key"); + + /* Create a file handler */ + std::fstream fp; + /* Open the file stream */ + fp.open(std::string(fname), std::fstream::out | std::fstream::trunc); + + /* Validate the file stream */ + openfpga::check_file_stream(fname, fp); + + /* Write the root node */ + fp << "" << "\n"; + + /* Write component by component */ + for (const FabricKeyId& key : fabric_key.keys()) { + write_xml_fabric_component_key(fp, fname, fabric_key, key); + } + + /* Finish writing the root node */ + fp << "" << "\n"; + + /* Close the file stream */ + fp.close(); +} diff --git a/libopenfpga/libfabrickey/src/write_xml_fabric_key.h b/libopenfpga/libfabrickey/src/write_xml_fabric_key.h new file mode 100644 index 000000000..f47c39a12 --- /dev/null +++ b/libopenfpga/libfabrickey/src/write_xml_fabric_key.h @@ -0,0 +1,16 @@ +#ifndef WRITE_XML_FABRIC_KEY_H +#define WRITE_XML_FABRIC_KEY_H + +/******************************************************************** + * Include header files that are required by function declaration + *******************************************************************/ +#include +#include "fabric_key.h" + +/******************************************************************** + * Function declaration + *******************************************************************/ +void write_xml_fabric_key(const char* fname, + const FabricKey& fabric_key); + +#endif diff --git a/libopenfpga/libfabrickey/test/test_fabric_key.cpp b/libopenfpga/libfabrickey/test/test_fabric_key.cpp new file mode 100644 index 000000000..51acfd818 --- /dev/null +++ b/libopenfpga/libfabrickey/test/test_fabric_key.cpp @@ -0,0 +1,34 @@ +/******************************************************************** + * Unit test functions to validate the correctness of + * 1. parser of data structures + * 2. writer of data structures + *******************************************************************/ +/* Headers from vtrutils */ +#include "vtr_assert.h" +#include "vtr_log.h" + +/* Headers from fabric key */ +#include "read_xml_fabric_key.h" +#include "write_xml_fabric_key.h" + +int main(int argc, const char** argv) { + /* Ensure we have only one or two argument */ + VTR_ASSERT((2 == argc) || (3 == argc)); + + + /* Parse the fabric key from an XML file */ + FabricKey test_key = read_xml_fabric_key(argv[1]); + VTR_LOG("Read the fabric key from an XML file: %s.\n", + argv[1]); + + /* Output the circuit library to an XML file + * This is optional only used when there is a second argument + */ + if (3 <= argc) { + write_xml_fabric_key(argv[2], test_key); + VTR_LOG("Echo the fabric key to an XML file: %s.\n", + argv[2]); + } +} + +