add fabric key library

This commit is contained in:
tangxifan 2020-06-12 00:07:04 -06:00
parent 278acee216
commit f081cef495
13 changed files with 448 additions and 0 deletions

View File

@ -3,3 +3,4 @@ add_subdirectory(libini)
add_subdirectory(libopenfpgashell)
add_subdirectory(libarchopenfpga)
add_subdirectory(libopenfpgautil)
add_subdirectory(libfabrickey)

View File

@ -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

View File

@ -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

View File

@ -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})

View File

@ -0,0 +1,7 @@
<fabric_key>
<key id="0" name="sb" value="0"/>
<key id="2" name="cb" value="10"/>
<key id="1" name="sb" value="7"/>
<key id="3" name="clb" value="53"/>
<key id="4" name="bram" value="32"/>
</fabric_key>

View File

@ -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] );
}

View File

@ -0,0 +1,59 @@
#ifndef FABRIC_KEY_H
#define FABRIC_KEY_H
/********************************************************************
* This file include the declaration of fabric key
*******************************************************************/
#include <string>
#include <map>
#include <array>
/* 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<FabricKeyId, FabricKeyId>::const_iterator fabric_key_iterator;
/* Create range */
typedef vtr::Range<fabric_key_iterator> 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<FabricKeyId, FabricKeyId> key_ids_;
/* Names for each key */
vtr::vector<FabricKeyId, std::string> key_names_;
/* Values for each key */
vtr::vector<FabricKeyId, size_t> key_values_;
};
#endif

View File

@ -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<fabric_key_id_tag> FabricKeyId;
/* Short declaration of class */
class FabricKey;
#endif

View File

@ -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 <string>
/* 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 <key> 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 <fabric> 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;
}

View File

@ -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

View File

@ -0,0 +1,69 @@
/********************************************************************
* This file includes functions that outputs a configuration protocol to XML format
*******************************************************************/
/* Headers from system goes first */
#include <string>
#include <algorithm>
/* 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" << "<key";
write_xml_attribute(fp, "id", size_t(component_key));
write_xml_attribute(fp, "name", fabric_key.key_name(component_key).c_str());
write_xml_attribute(fp, "value", fabric_key.key_value(component_key));
fp << "/>" << "\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 << "<fabric_key>" << "\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 << "</fabric_key>" << "\n";
/* Close the file stream */
fp.close();
}

View File

@ -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 <fstream>
#include "fabric_key.h"
/********************************************************************
* Function declaration
*******************************************************************/
void write_xml_fabric_key(const char* fname,
const FabricKey& fabric_key);
#endif

View File

@ -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]);
}
}