Write out an encrypted netlist

From Verific Design Automation FAQ
Jump to: navigation, search
#include <iostream>
#include <cstring>

#include "veri_file.h"

#include "DataBase.h"
#include "VeriWrite.h"

#include "Strings.h"
#include "Message.h"
#include "Protect.h"

#ifdef VERIFIC_NAMESPACE
using namespace Verific ;
#endif

// Derive a class from Protect
class VFC_DLL_PORT Cipher : public Protect
{
public:
    Cipher() : Protect(64) {}
    virtual ~Cipher() {}

    virtual unsigned encrypt(const char *in_buf, char *out_buf, unsigned size) ;
    virtual unsigned decrypt(const char *in_buf, char *out_buf, unsigned size) ;
    virtual char *decrypt() ;
    virtual char * GetEncryptionHeader() ;
    virtual char * GetEncryptionFooter() ;
} ;

unsigned
Cipher::encrypt(const char *in_buf, char *out_buf, unsigned size)
{
    std::memset(out_buf, 0, size) ; // set all bytes to '\0'
    unsigned in_len = Strings::len(in_buf) ;

    unsigned i ;
    for (i = 0 ; i < in_len ; ++i) {
        out_buf[i] = in_buf[i] + 1 ; // increment the ASCII value
    }
    return size ;
} ;

unsigned
Cipher::decrypt(const char *in_buf, char *out_buf, unsigned size)
{
    std::memset(out_buf, 0, size) ; // set all bytes to '\0'
    unsigned in_len = Strings::len(in_buf) ;

    unsigned i ;
    for (i = 0 ; i < in_len ; ++i) {
        out_buf[i] = in_buf[i] - 1 ; // decrement the ASCII value
    }
    return size ;
} ;

char *
Cipher::decrypt()
{
    const Directive *directive = GetValue("data_block") ;
    char *out_buf = Strings::save(directive->GetStringValue()) ;
    decrypt(directive->GetStringValue(), out_buf, Strings::len(out_buf)) ;
    return out_buf ;
}

char *
Cipher::GetEncryptionHeader()
{
    // Return the encryption header
    return Strings::save("`pragma protect begin_protected\n`pragma protect data_block") ;
}


char *
Cipher::GetEncryptionFooter()
{
    // Return the encryption the footer
    return Strings::save("`pragma protect end_protected") ;
}

// Call back function to specify if this module is to be encrypted or not
unsigned
encrypt_module_func(const char *mod_name)
{
    if (!mod_name) return 0 ;

    //return 1 ; // Enable this line to protect all the modules
    
    if (Strings::compare(mod_name, "bot1") || Strings::compare(mod_name, "bot2")) {
        Message::Info(0, "Encrypting module ", mod_name) ;
        return 1 ; // return 1 to encrypt this module
    }

    return 0 ;
}

int main()
{

    // Now read in top-level design. In case of failure return.
    if (!veri_file::Read("test.v", "work", veri_file::VERILOG_2K)) {
        // Here, design analysis and elaboration failed
        return 1 ;
    }

    // Get a handle to the top-level netlist
    Netlist *top = Netlist::PresentDesign() ;

    Cipher cipher ;
    VeriWrite writter ;

    // Set the protection object
    writter.SetProtectionObject(&cipher) ;
    writter.RegisterEncryptModule(encrypt_module_func) ;

    // Write the netlist
    if (!writter.WriteFile("test.v.golden.new", top)) return 1 ;

    Libset::Reset() ;
    veri_file::Reset() ;

    // Analyze the encrypted file
    veri_file::SetPragmaProtectObject(&cipher) ;
    if (!veri_file::Analyze("test.v.golden.new", veri_file::VERILOG_2K, "work")) return 1 ;

    // PrettyPrint the analyzed file
    if (!veri_file::PrettyPrint("pp_test.v.golden.new", 0, "work")) return 1 ;

    return 0 ;
}