Merge branch 'ganesh_dev' of https://github.com/LNIS-Projects/OpenFPGA into refactoring

This commit is contained in:
tangxifan 2019-11-01 18:27:27 -06:00
commit e2b042c61c
18 changed files with 1415 additions and 190 deletions

View File

@ -2,6 +2,8 @@
#add_subdirectory(libarchfpga)
add_subdirectory(libvtrutil)
add_subdirectory(liblog)
add_subdirectory(external)
#add_subdirectory(external)
#add_subdirectory(libpugiutil)
#add_subdirectory(libeasygl)
#add_subdirectory(librtlnumber)

1
libs/external/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1 @@
add_subdirectory(libini)

12
libs/external/libini/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 2.8.12)
project(libini)
file(GLOB_RECURSE LIB_HEADERS src/*.h)
files_to_dirs(LIB_HEADERS LIB_INCLUDE_DIRS)
#Create the library
add_library(libini STATIC
${LIB_HEADERS})
target_include_directories(libini PUBLIC ${LIB_INCLUDE_DIRS})
set_target_properties(libini PROPERTIES PREFIX "" LINKER_LANGUAGE CXX)

755
libs/external/libini/src/ini.h vendored Executable file
View File

@ -0,0 +1,755 @@
/*
* The MIT License (MIT)
* Copyright (c) 2018 Danijel Durakovic
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
///////////////////////////////////////////////////////////////////////////////
//
// /mINI/ v0.9.7
// An INI file reader and writer for the modern age.
//
///////////////////////////////////////////////////////////////////////////////
//
// A tiny utility library for manipulating INI files with a straightforward
// API and a minimal footprint. It conforms to the (somewhat) standard INI
// format - sections and keys are case insensitive and all leading and
// trailing whitespace is ignored. Comments are lines that begin with a
// semicolon. Trailing comments are allowed on section lines.
//
// Files are read on demand, upon which data is kept in memory and the file
// is closed. This utility supports lazy writing, which only writes changes
// and updates to a file and preserves custom formatting and comments. A lazy
// write invoked by a write() call will read the output file, find what
// changes have been made and update the file accordingly. If you only need to
// generate files, use generate() instead. Section and key order is preserved
// on read, write and insert.
//
///////////////////////////////////////////////////////////////////////////////
//
// /* BASIC USAGE EXAMPLE: */
//
// /* read from file */
// mINI::INIFile file("myfile.ini");
// mINI::INIStructure ini;
// file.read(ini);
//
// /* read value; gets a reference to actual value in the structure.
// if key or section don't exist, a new empty value will be created */
// std::string& value = ini["section"]["key"];
//
// /* read value safely; gets a copy of value in the structure.
// does not alter the structure */
// std::string value = ini.get("section").get("key");
//
// /* set or update values */
// ini["section"]["key"] = "value";
//
// /* set multiple values */
// ini["section2"].set({
// {"key1", "value1"},
// {"key2", "value2"}
// });
//
// /* write updates back to file, preserving comments and formatting */
// file.write(ini);
//
// /* or generate a file (overwrites the original) */
// file.generate(ini);
//
///////////////////////////////////////////////////////////////////////////////
//
// Long live the INI file!!!
//
///////////////////////////////////////////////////////////////////////////////
#ifndef MINI_INI_H_
#define MINI_INI_H_
#include <string>
#include <sstream>
#include <algorithm>
#include <utility>
#include <unordered_map>
#include <vector>
#include <memory>
#include <fstream>
#include <sys/stat.h>
namespace mINI
{
namespace INIStringUtil
{
const std::string whitespaceDelimiters = " \t\n\r\f\v";
inline void trim(std::string &str)
{
str.erase(str.find_last_not_of(whitespaceDelimiters) + 1);
str.erase(0, str.find_first_not_of(whitespaceDelimiters));
}
#ifndef MINI_CASE_SENSITIVE
inline void toLower(std::string &str)
{
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
}
#endif
inline void replace(std::string &str, std::string const &a, std::string const &b)
{
if (!a.empty())
{
std::size_t pos = 0;
while ((pos = str.find(a, pos)) != std::string::npos)
{
str.replace(pos, a.size(), b);
pos += b.size();
}
}
}
#ifdef _WIN32
const std::string endl = "\r\n";
#else
const std::string endl = "\n";
#endif
}; // namespace INIStringUtil
template <typename T>
class INIMap
{
private:
using T_DataIndexMap = std::unordered_map<std::string, std::size_t>;
using T_DataItem = std::pair<std::string, T>;
using T_DataContainer = std::vector<T_DataItem>;
using T_MultiArgs = typename std::vector<std::pair<std::string, T>>;
T_DataIndexMap dataIndexMap;
T_DataContainer data;
inline std::size_t setEmpty(std::string &key)
{
std::size_t index = data.size();
dataIndexMap[key] = index;
data.emplace_back(key, T());
return index;
}
public:
using const_iterator = typename T_DataContainer::const_iterator;
INIMap() {}
INIMap(INIMap const &other)
{
std::size_t data_size = other.data.size();
for (std::size_t i = 0; i < data_size; ++i)
{
auto const &key = other.data[i].first;
auto const &obj = other.data[i].second;
data.emplace_back(key, obj);
}
dataIndexMap = T_DataIndexMap(other.dataIndexMap);
}
T &operator[](std::string key)
{
INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
bool hasIt = (it != dataIndexMap.end());
std::size_t index = (hasIt) ? it->second : setEmpty(key);
return data[index].second;
}
T get(std::string key) const
{
INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it == dataIndexMap.end())
{
return T();
}
return T(data[it->second].second);
}
bool has(std::string key) const
{
INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
return (dataIndexMap.count(key) == 1);
}
void set(std::string key, T obj)
{
INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it != dataIndexMap.end())
{
data[it->second].second = obj;
}
else
{
dataIndexMap[key] = data.size();
data.emplace_back(key, obj);
}
}
void set(T_MultiArgs const &multiArgs)
{
for (auto const &it : multiArgs)
{
auto const &key = it.first;
auto const &obj = it.second;
set(key, obj);
}
}
bool remove(std::string key)
{
INIStringUtil::trim(key);
#ifndef MINI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it != dataIndexMap.end())
{
std::size_t index = it->second;
data.erase(data.begin() + index);
dataIndexMap.erase(it);
for (auto &it2 : dataIndexMap)
{
auto &vi = it2.second;
if (vi > index)
{
vi--;
}
}
return true;
}
return false;
}
void clear()
{
data.clear();
dataIndexMap.clear();
}
std::size_t size() const
{
return data.size();
}
const_iterator begin() const { return data.begin(); }
const_iterator end() const { return data.end(); }
};
using INIStructure = INIMap<INIMap<std::string>>;
namespace INIParser
{
using T_ParseValues = std::pair<std::string, std::string>;
enum class PDataType : char
{
PDATA_NONE,
PDATA_COMMENT,
PDATA_SECTION,
PDATA_KEYVALUE,
PDATA_UNKNOWN
};
inline PDataType parseLine(std::string line, T_ParseValues &parseData)
{
parseData.first.clear();
parseData.second.clear();
INIStringUtil::trim(line);
if (line.empty())
{
return PDataType::PDATA_NONE;
}
char firstCharacter = line[0];
if (firstCharacter == ';')
{
return PDataType::PDATA_COMMENT;
}
if (firstCharacter == '[')
{
auto commentAt = line.find_first_of(';');
if (commentAt != std::string::npos)
{
line = line.substr(0, commentAt);
}
auto closingBracketAt = line.find_last_of(']');
if (closingBracketAt != std::string::npos)
{
auto section = line.substr(1, closingBracketAt - 1);
INIStringUtil::trim(section);
parseData.first = section;
return PDataType::PDATA_SECTION;
}
}
auto lineNorm = line;
INIStringUtil::replace(lineNorm, "\\=", " ");
auto equalsAt = lineNorm.find_first_of('=');
if (equalsAt != std::string::npos)
{
auto key = line.substr(0, equalsAt);
INIStringUtil::trim(key);
INIStringUtil::replace(key, "\\=", "=");
auto value = line.substr(equalsAt + 1);
INIStringUtil::trim(value);
parseData.first = key;
parseData.second = value;
return PDataType::PDATA_KEYVALUE;
}
return PDataType::PDATA_UNKNOWN;
}
}; // namespace INIParser
class INIReader
{
public:
using T_LineData = std::vector<std::string>;
using T_LineDataPtr = std::shared_ptr<T_LineData>;
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
T_LineData readFile()
{
std::string fileContents;
fileReadStream.seekg(0, std::ios::end);
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0)
{
return output;
}
std::string buffer;
buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i)
{
char &c = fileContents[i];
if (c == '\n')
{
output.emplace_back(buffer);
buffer.clear();
continue;
}
if (c != '\0' && c != '\r')
{
buffer += c;
}
}
output.emplace_back(buffer);
return output;
}
public:
INIReader(std::string const &filename, bool keepLineData = false)
{
fileReadStream.open(filename, std::ios::in | std::ios::binary);
if (keepLineData)
{
lineData = std::make_shared<T_LineData>();
}
}
~INIReader() {}
bool operator>>(INIStructure &data)
{
if (!fileReadStream.is_open())
{
return false;
}
T_LineData fileLines = readFile();
std::string section;
bool inSection = false;
INIParser::T_ParseValues parseData;
for (auto const &line : fileLines)
{
auto parseResult = INIParser::parseLine(line, parseData);
if (parseResult == INIParser::PDataType::PDATA_SECTION)
{
inSection = true;
data[section = parseData.first];
}
else if (inSection && parseResult == INIParser::PDataType::PDATA_KEYVALUE)
{
auto const &key = parseData.first;
auto const &value = parseData.second;
data[section][key] = value;
}
if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN)
{
if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection)
{
continue;
}
lineData->emplace_back(line);
}
}
return true;
}
T_LineDataPtr getLines()
{
return lineData;
}
};
class INIGenerator
{
private:
std::ofstream fileWriteStream;
public:
bool prettyPrint = false;
INIGenerator(std::string const &filename)
{
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
}
~INIGenerator() {}
bool operator<<(INIStructure const &data)
{
if (!fileWriteStream.is_open())
{
return false;
}
if (!data.size())
{
return true;
}
auto it = data.begin();
for (;;)
{
auto const &section = it->first;
auto const &collection = it->second;
fileWriteStream
<< "["
<< section
<< "]";
if (collection.size())
{
fileWriteStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;)
{
auto key = it2->first;
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
fileWriteStream
<< key
<< ((prettyPrint) ? " = " : "=")
<< value;
if (++it2 == collection.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
}
}
if (++it == data.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
if (prettyPrint)
{
fileWriteStream << INIStringUtil::endl;
}
}
return true;
}
};
class INIWriter
{
private:
using T_LineData = std::vector<std::string>;
using T_LineDataPtr = std::shared_ptr<T_LineData>;
std::string filename;
T_LineData getLazyOutput(T_LineDataPtr const &lineData, INIStructure &data, INIStructure &original)
{
T_LineData output;
INIParser::T_ParseValues parseData;
std::string sectionCurrent;
bool parsingSection = false;
bool continueToNextSection = false;
bool discardNextEmpty = false;
bool writeNewKeys = false;
std::size_t lastKeyLine = 0;
for (auto line = lineData->begin(); line != lineData->end(); ++line)
{
if (!writeNewKeys)
{
auto parseResult = INIParser::parseLine(*line, parseData);
if (parseResult == INIParser::PDataType::PDATA_SECTION)
{
if (parsingSection)
{
writeNewKeys = true;
parsingSection = false;
--line;
continue;
}
sectionCurrent = parseData.first;
if (data.has(sectionCurrent))
{
parsingSection = true;
continueToNextSection = false;
discardNextEmpty = false;
output.emplace_back(*line);
lastKeyLine = output.size();
}
else
{
continueToNextSection = true;
discardNextEmpty = true;
continue;
}
}
else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE)
{
if (continueToNextSection)
{
continue;
}
if (data.has(sectionCurrent))
{
auto &collection = data[sectionCurrent];
auto const &key = parseData.first;
auto const &value = parseData.second;
if (collection.has(key))
{
auto outputValue = collection[key];
if (value == outputValue)
{
output.emplace_back(*line);
}
else
{
INIStringUtil::trim(outputValue);
auto lineNorm = *line;
INIStringUtil::replace(lineNorm, "\\=", " ");
auto equalsAt = lineNorm.find_first_of('=');
auto valueAt = lineNorm.find_first_not_of(
INIStringUtil::whitespaceDelimiters,
equalsAt + 1);
std::string outputLine = line->substr(0, valueAt);
if (prettyPrint && equalsAt + 1 == valueAt)
{
outputLine += " ";
}
outputLine += outputValue;
output.emplace_back(outputLine);
}
lastKeyLine = output.size();
}
}
}
else
{
if (discardNextEmpty && line->empty())
{
discardNextEmpty = false;
}
else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN)
{
output.emplace_back(*line);
}
}
}
if (writeNewKeys || std::next(line) == lineData->end())
{
T_LineData linesToAdd;
if (data.has(sectionCurrent) && original.has(sectionCurrent))
{
auto const &collection = data[sectionCurrent];
auto const &collectionOriginal = original[sectionCurrent];
for (auto const &it : collection)
{
auto key = it.first;
if (collectionOriginal.has(key))
{
continue;
}
auto value = it.second;
INIStringUtil::replace(key, "=", "\\=");
INIStringUtil::trim(value);
linesToAdd.emplace_back(
key + ((prettyPrint) ? " = " : "=") + value);
}
}
if (!linesToAdd.empty())
{
output.insert(
output.begin() + lastKeyLine,
linesToAdd.begin(),
linesToAdd.end());
}
if (writeNewKeys)
{
writeNewKeys = false;
--line;
}
}
}
for (auto const &it : data)
{
auto const &section = it.first;
if (original.has(section))
{
continue;
}
if (prettyPrint && output.size() > 0 && !output.back().empty())
{
output.emplace_back();
}
output.emplace_back("[" + section + "]");
auto const &collection = it.second;
for (auto const &it2 : collection)
{
auto key = it2.first;
auto value = it2.second;
INIStringUtil::replace(key, "=", "\\=");
INIStringUtil::trim(value);
output.emplace_back(
key + ((prettyPrint) ? " = " : "=") + value);
}
}
return output;
}
public:
bool prettyPrint = false;
INIWriter(std::string const &filename)
: filename(filename)
{
}
~INIWriter() {}
bool operator<<(INIStructure &data)
{
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists)
{
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
{
INIReader reader(filename, true);
if ((readSuccess = reader >> originalData))
{
lineData = reader.getLines();
}
}
if (!readSuccess)
{
return false;
}
T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open())
{
if (output.size())
{
auto line = output.begin();
for (;;)
{
fileWriteStream << *line;
if (++line == output.end())
{
break;
}
fileWriteStream << INIStringUtil::endl;
}
}
return true;
}
return false;
}
};
class INIFile
{
private:
std::string filename;
public:
INIFile(std::string const &filename)
: filename(filename)
{
}
~INIFile() {}
bool read(INIStructure &data) const
{
if (data.size())
{
data.clear();
}
if (filename.empty())
{
return false;
}
INIReader reader(filename);
return reader >> data;
}
bool generate(INIStructure const &data, bool pretty = false) const
{
if (filename.empty())
{
return false;
}
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
}
bool write(INIStructure &data, bool pretty = false) const
{
if (filename.empty())
{
return false;
}
INIWriter writer(filename);
writer.prettyPrint = pretty;
return writer << data;
}
};
} // namespace mINI
#endif // MINI_INI_H_

View File

@ -5,7 +5,7 @@
// Coder : Xifan TANG
//-----------------------------------------------------
//------ Include defines: preproc flags -----
`include "./SRC/fpga_defines.v"
// `include "./SRC/fpga_defines.v"
module static_dff (
/* Global ports go first */
input set, // set input

View File

@ -0,0 +1,20 @@
# = = = = = = = = = = = = = = = = = = = = = =
# Auto generated using OpenFPGA
# = = = = = = = = = = = = = = = = = = = = = =
# Benchmark Source Files
read_verilog -container r -libname WORK -05 { ${SOURCE_DESIGN_FILES} }
set_top r:${SOURCE_TOP_MODULE}
# Benchmark Implementation Files
read_verilog -container i -libname WORK -05 { ${IMPL_DESIGN_FILES} }
set_top i:${IMPL_TOP_DIR}
match
# Port Mapping
${PORT_MAP_LIST}
# Register Mapping
${REGISTER_MAP_LIST}
verify

View File

@ -0,0 +1,71 @@
proc create_project {projectname project_path} {
#Switch to the modelsim folder to create the project
set libname $projectname
set initfile /uusoc/facility/cad_tools/Mentor/modelsim10.7b/modeltech/modelsim.ini
project new $project_path/$projectname $projectname $libname $initfile 0
}
proc create_project_with_close {projectname modelsim_path} {
#Get the current project name
set project_env [project env]
if {$project_env eq ""} {
#If string empty (no project)
create_project $projectname $modelsim_path
} else {
#If string not empty (a project is loaded so clsoe it first)
project close
create_project $projectname $modelsim_path
}
}
proc add_files_project {verilog_files} {
#Get the length of the list
set listlength [llength $verilog_files]
#Add the verilog files one by one
for {set x 0} {$x<$listlength} {incr x} {
project addfile [lindex $verilog_files $x]
}
}
proc add_waves {top_tb} {
add wave -position insertpoint sim:/$top_tb/*
}
proc runsim {simtime unit} {
run $simtime $unit
}
#Top procedure to create enw project
proc top_create_new_project {projectname verilog_files modelsim_path simtime unit top_tb} {
#Create the project
create_project_with_close $projectname $modelsim_path
#Add the verilog files
add_files_project $verilog_files
#Compile all the files
set myFiles [project filenames]
foreach x $myFiles {
vlog +define+ENABLE_TIMING +define+ENABLE_SIGNAL_INITIALIZATION $x
}
#Start the simulation
vsim $projectname.$top_tb -voptargs=+acc
#Add the waves
add_waves top_tb
#run the simulation
runsim $simtime $unit
#Fit the window view
wave zoom full
}
#Top proc to recompile files and re run the simulation
proc top_rerun_sim {simtime unit top_tb} {
#Save actual format
set myLoc [pwd]
write format wave -window .main_pane.wave.interior.cs.body.pw.wf $myLoc/relaunch.do
quit -sim
#Compile updated verilog files
set myFiles [project filenames]
foreach x $myFiles {
vlog +define+ENABLE_TIMING +define+ENABLE_SIGNAL_INITIALIZATION $x
}
set projectname K4n4_test_fpga_msim
vsim $projectname.$top_tb -voptargs=+acc -do relaunch.do
#run the simulation
run $simtime $unit
}

View File

@ -0,0 +1,37 @@
echo "=========================="
pwd
echo "=========================="
set projectname ${PROJECTNAME}
set benchmark ${BENCHMARK}
set top_tb ${TOP_TB}
#in ms
set simtime ${SIMTIME}
set unit ${UNIT}
#Path were both tcl script are located
set verilog_path ${VERILOG_PATH}
set project_path "${MODELSIM_PROJ_DIR}/msim_projects/"
#Path were the verilog files are located
set verilog_path ${VERILOG_PATH}
set verilog_files [list \
${VERILOG_PATH}${VERILOG_FILE1} \
${VERILOG_PATH}${VERILOG_FILE2} \
${VERILOG_PATH}fpga_defines.v
]
#Source the tcl script
source ${MODELSIM_PROJ_DIR}/${BENCHMARK}_autocheck_proc.tcl
#Execute the top level procedure
try {
top_create_new_project $$projectname $$verilog_files $$project_path $$simtime $$unit $$top_tb
} finally {
quit
}
#Relaunch simulation

View File

@ -1,8 +0,0 @@
read_verilog -container r -libname WORK -05 { ${SOURCE_DESIGN} }
set_top r:${SOURCE_TOP_DIR}
read_verilog -container i -libname WORK -05 { ${IMPL_DESIGN} }
set_top i:${IMPL_TOP_DIR}
match
${MATCH_MODUEL_LIST}
verify

View File

@ -0,0 +1,105 @@
from string import Template
import sys
import os
import pprint
import argparse
import subprocess
import logging
from pprint import pprint
from configparser import ConfigParser
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configure logging system
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
logging.basicConfig(level=logging.INFO, stream=sys.stdout,
format='%(levelname)s (%(threadName)10s) - %(message)s')
logger = logging.getLogger('Modelsim_run_log')
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Parse commandline arguments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='+')
parser.add_argument('--formality_template', type=str,
help="Modelsim verification template file")
parser.add_argument('--run_sim', action="store_true",
help="Execute generated script in formality")
args = parser.parse_args()
# Consider default formality script template
if not args.formality_template:
task_script_dir = os.path.dirname(os.path.abspath(__file__))
args.formality_template = os.path.join(task_script_dir, os.pardir,
"misc", "formality_template.tcl")
args.formality_template = os.path.abspath(args.formality_template)
def main():
for eachFile in args.files:
eachFile = os.path.abspath(eachFile)
pDir = os.path.dirname(eachFile)
os.chdir(pDir)
config = ConfigParser()
config.read(eachFile)
port_map = ("set_user_match r:%s/%%s i:/WORK/%%s -type port -noninverted" % (
"/WORK/" + config["BENCHMARK_INFO"]["src_top_module"]
))
cell_map = ("set_user_match r:%s/%%s i:/WORK/%%s -type cell -noninverted" % (
"/WORK/" + config["BENCHMARK_INFO"]["src_top_module"]
))
lables = {
"SOURCE_DESIGN_FILES": config["BENCHMARK_INFO"]["benchmark_netlist"],
"SOURCE_TOP_MODULE": "/WORK/" + config["BENCHMARK_INFO"]["src_top_module"],
"IMPL_DESIGN_FILES": " ".join(
[val for key, val in config["FPGA_INFO"].items()
if "impl_netlist_" in key]),
"IMPL_TOP_DIR": "/WORK/" + config["FPGA_INFO"]["impl_top_module"],
"PORT_MAP_LIST": "\n".join([port_map %
ele for ele in
config["PORT_MATCHING"].items()]),
"REGISTER_MAP_LIST": "\n".join([cell_map %
ele for ele in
config["REGISTER_MATCH"].items()]),
}
tmpl = Template(open(args.formality_template, encoding='utf-8').read())
with open(os.path.join(pDir, "Output.tcl"), 'w', encoding='utf-8') as tclout:
tclout.write(tmpl.substitute(lables))
if args.run_sim:
formality_run_string = ["formality", "-file", "Output.tcl"]
run_command("Formality Run", "formality_run.log", formality_run_string)
else:
with open("Output.tcl", 'r', encoding='utf-8') as tclout:
print(tclout.read())
def run_command(taskname, logfile, command, exit_if_fail=True):
os.chdir(os.pardir)
logger.info("Launching %s " % taskname)
with open(logfile, 'w+') as output:
try:
output.write(" ".join(command)+"\n")
process = subprocess.run(command,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
output.write(process.stdout)
if process.returncode:
logger.error("%s run failed with returncode %d" %
(taskname, process.returncode))
except (Exception, subprocess.CalledProcessError) as e:
logger.exception("failed to execute %s" % taskname)
return None
logger.info("%s is written in file %s" % (taskname, logfile))
return process.stdout
if __name__ == "__main__":
main()

View File

@ -234,10 +234,11 @@ def main():
if (args.fpga_flow == "yosys_vpr"):
logger.info('Running "yosys_vpr" Flow')
run_yosys_with_abc()
# TODO Make it optional if activity file is provided
run_ace2()
run_pro_blif_3arg()
if args.power:
run_ace2()
run_pro_blif_3arg()
run_rewrite_verilog()
run_rewrite_verilog()
if (args.fpga_flow == "vpr_blif"):
collect_files_for_vpr()
# if (args.fpga_flow == "vtr"):
@ -621,7 +622,7 @@ def run_vpr():
min_channel_width = run_standard_vpr(
args.top_module+".blif",
args.fix_route_chan_width,
args.top_module+"_fr_chan_width.txt")
args.top_module+"_fr_chan_width_vpr.txt")
logger.info("Fixed routing channel successfully routed with %d width" %
min_channel_width)
extract_vpr_stats(args.top_module+"_fr_chan_width.txt")
@ -642,13 +643,13 @@ def run_standard_vpr(bench_blif, fixed_chan_width, logfile, route_only=False):
"--place_file", args.top_module+"_vpr.place",
"--route_file", args.top_module+"_vpr.route",
"--full_stats", "--nodisp",
"--activity_file", args.top_module+"_ace_out.act",
]
if route_only:
command += ["--route"]
# Power options
if args.power:
command += ["--power",
"--activity_file", args.top_module+"_ace_out.act",
"--tech_properties", args.power_tech]
# packer options
if args.vpr_timing_pack_off:
@ -700,7 +701,7 @@ def run_standard_vpr(bench_blif, fixed_chan_width, logfile, route_only=False):
command += ["--fpga_spice_testbench_load_extraction", "off"]
# FPGA Verilog options
if (args.power and args.vpr_fpga_verilog):
if args.vpr_fpga_verilog:
command += ["--fpga_verilog"]
if args.vpr_fpga_verilog_dir:
command += ["--fpga_verilog_dir", args.vpr_fpga_verilog_dir]
@ -710,7 +711,8 @@ def run_standard_vpr(bench_blif, fixed_chan_width, logfile, route_only=False):
command += ["--fpga_verilog_print_input_blif_testbench"]
if args.vpr_fpga_verilog_print_autocheck_top_testbench:
command += ["--fpga_verilog_print_autocheck_top_testbench",
args.top_module+"_output_verilog.v"]
# args.vpr_fpga_verilog_print_autocheck_top_testbench]
os.path.join(args.run_dir, args.top_module+"_output_verilog.v")]
if args.vpr_fpga_verilog_include_timing:
command += ["--fpga_verilog_include_timing"]
if args.vpr_fpga_verilog_explicit_mapping:
@ -835,7 +837,7 @@ def run_rewrite_verilog():
run_command("Yosys", "yosys_output.txt", command)
def run_netlists_verification():
def run_netlists_verification(exit_if_fail=True):
ExecTime["VerificationStart"] = time.time()
compiled_file = "compiled_"+args.top_module
# include_netlists = args.top_module+"_include_netlists.v"

View File

@ -367,7 +367,7 @@ def create_run_command(curr_job_dir, archfile, benchmark_obj, param, task_conf):
if task_gc.getboolean("verilog_output"):
command += ["--vpr_fpga_verilog"]
command += ["--vpr_fpga_verilog_dir", "."]
command += ["--vpr_fpga_verilog_dir", curr_job_dir]
command += ["--vpr_fpga_x2p_rename_illegal_port"]
# Add other paramters to pass

View File

@ -1,10 +1,12 @@
from string import Template
import sys
import os
import pprint
import argparse
import subprocess
import logging
from pprint import pprint
from configparser import ConfigParser
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Configure logging system
@ -13,58 +15,118 @@ logging.basicConfig(level=logging.INFO, stream=sys.stdout,
format='%(levelname)s (%(threadName)10s) - %(message)s')
logger = logging.getLogger('Modelsim_run_log')
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
# Parse commandline arguments
# = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='+')
parser.add_argument('--modelsim_template', type=str,
help="Modelsim verification template file")
parser.add_argument('files', nargs='+',
help="Pass SimulationDeckInfo generated by OpenFPGA flow")
parser.add_argument('--modelsim_proc_tmpl', type=str,
help="Modelsim proc template file")
parser.add_argument('--modelsim_runsim_tmpl', type=str,
help="Modelsim runsim template file")
parser.add_argument('--run_sim', action="store_true",
help="Execute generated script in formality")
parser.add_argument('--modelsim_proj_dir',
help="Provide modelsim project directory")
parser.add_argument('--modelsim_proj_name',
help="Provide modelsim project name")
parser.add_argument('--modelsim_ini', type=str,
default="/uusoc/facility/cad_tools/Mentor/modelsim10.7b/modeltech/modelsim.ini",
help="Skip any confirmation")
parser.add_argument('--skip_prompt', action='store_true',
help='Skip any confirmation')
args = parser.parse_args()
# Consider default formality script template
task_script_dir = os.path.dirname(os.path.abspath(__file__))
if not args.modelsim_proc_tmpl:
args.modelsim_proc_tmpl = os.path.join(task_script_dir, os.pardir,
"misc", "modelsim_proc.tcl")
if not args.modelsim_runsim_tmpl:
args.modelsim_runsim_tmpl = os.path.join(task_script_dir, os.pardir,
"misc", "modelsim_runsim.tcl")
if not args.modelsim_template:
task_script_dir = os.path.dirname(os.path.abspath(__file__))
args.modelsim_template = os.path.join(task_script_dir, os.pardir,
"misc", "modelsim_template.j2")
args.modelsim_template = os.path.abspath(args.modelsim_template)
args.modelsim_proc_tmpl = os.path.abspath(args.modelsim_proc_tmpl)
args.modelsim_runsim_tmpl = os.path.abspath(args.modelsim_runsim_tmpl)
def main():
for eachFile in args.files:
eachFile = os.path.abspath(eachFile)
directory = os.path.dirname(eachFile)
os.chdir(directory)
with open(eachFile, 'r') as fp:
lines = fp.read().split("\n")
SplitL = [indx for indx, eachL in enumerate(lines) if eachL == ""]
SplitL = list(zip([0] + SplitL[:-1], SplitL))
for indx, eachSection in enumerate(SplitL):
SplitL[indx] = list(filter(None, lines[slice(*eachSection)]))
pDir = os.path.dirname(eachFile)
os.chdir(pDir)
match_str = "set_user_match r:%s i:%s -type port -noninverted"
lables = {"SOURCE_DESIGN": " ".join(SplitL[0]),
"SOURCE_TOP_DIR": "/WORK/" + " ".join(SplitL[1]),
"IMPL_DESIGN": " ".join(SplitL[2]),
"IMPL_TOP_DIR": "/WORK/" + " ".join(SplitL[3]),
"MATCH_MODUEL_LIST": "\n".join([match_str % tuple(eachPort.split()) for eachPort in SplitL[4]])
}
config = ConfigParser()
config.read(eachFile)
config = config["SIMULATION_DECK"]
tmpl = Template(open(args.modelsim_template, encoding='utf-8').read())
with open("Output.tcl", 'w', encoding='utf-8') as tclout:
tclout.write(tmpl.substitute(lables))
if args.run_sim:
formality_run_string = ["formality", "-file", "Output.tcl"]
run_command("Modelsim run", "modelsim_run.log", formality_run_string)
else:
with open("Output.tcl", 'r', encoding='utf-8') as tclout:
print(tclout.read())
# Resolve project Modelsim project path
if not args.modelsim_proj_dir:
args.modelsim_run_dir = os.path.dirname(os.path.abspath(eachFile))
args.modelsim_proj_dir = os.path.join(
args.modelsim_run_dir, "MMSIM2")
logger.info(f"Modelsim project dir not provide " +
f"using default {args.modelsim_proj_dir} directory")
if not args.skip_prompt:
input("Press Enter to continue, Ctrl+C to abort")
args.modelsim_proj_dir = os.path.abspath(args.modelsim_proj_dir)
config["MODELSIM_PROJ_DIR"] = args.modelsim_proj_dir
if not os.path.exists(args.modelsim_proj_dir):
os.makedirs(args.modelsim_proj_dir)
# Resolve Modelsim Project name
if not args.modelsim_proj_name:
args.modelsim_proj_name = config["BENCHMARK"] + "_MMSIM"
logger.info(f"Modelsim project name not provide " +
f"using default {args.modelsim_proj_name} directory")
if not args.skip_prompt:
input("Press Enter to continue, Ctrl+C to abort")
config["MODELSIM_PROJ_NAME"] = args.modelsim_proj_name
config["MODELSIM_INI"] = args.modelsim_ini
# Modify the variables in config file here
config["TOP_TB"] = os.path.splitext(config["TOP_TB"])[0]
# pass
# Write final template file
# Write runsim file
tmpl = Template(open(args.modelsim_runsim_tmpl,
encoding='utf-8').read())
runsim_filename = os.path.join(args.modelsim_proj_dir,
"%s_runsim.tcl" % config['BENCHMARK'])
logger.info(f"Creating tcl script at : {runsim_filename}")
with open(runsim_filename, 'w', encoding='utf-8') as tclout:
tclout.write(tmpl.substitute(config))
# Write proc file
proc_filename = os.path.join(args.modelsim_proj_dir,
"%s_autocheck_proc.tcl" % config['BENCHMARK'])
logger.info(f"Creating tcl script at : {proc_filename}")
with open(proc_filename, 'w', encoding='utf-8') as tclout:
tclout.write(open(args.modelsim_proc_tmpl,
encoding='utf-8').read())
# Execute modelsim
if args.run_sim:
os.chdir(args.modelsim_run_dir)
print(args.modelsim_run_dir)
modelsim_run_cmd = ["vsim", "-c", "-do", runsim_filename]
run_command("ModelSim Run", "modelsim_run.log",
modelsim_run_cmd)
else:
logger.info("Created runsim and proc files")
logger.info(f"runsim_filename {runsim_filename}")
logger.info(f"proc_filename {proc_filename}")
def run_command(taskname, logfile, command, exit_if_fail=True):
# os.chdir(os.pardir)
logger.info("Launching %s " % taskname)
with open(logfile, 'w+') as output:
try:
output.write(os.getcwd() + "\n")
output.write(" ".join(command)+"\n")
process = subprocess.run(command,
check=True,

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12)
if (${CMAKE_VERSION} VERSION_GREATER "3.8")
#For cmake >= 3.9 INTERPROCEDURAL_OPTIMIZATION behaviour we need to explicitly
#set the cmake policy version number
cmake_policy(VERSION 3.9)
cmake_policy(VERSION 3.9)
# If we are using verison < 3.9 then setting INTERPROCEDURAL_OPTIMIZATION
# has no effect unless an Intel compiler is used
@ -29,13 +29,13 @@ else ()
endif()
if (NOT ENABLE_VPR_GRAPHIC_CXX_FLAG)
# Add a flag to notify compiler not to consider graphic-related source codes
# Add a flag to notify compiler not to consider graphic-related source codes
set (DISABLE_GRAPHIC_FLAGS "-DNO_GRAPHICS")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DISABLE_GRAPHIC_FLAGS}")
message(STATUS "Add flags to disable graphics in VPR compilation: ${DISABLE_GRAPHIC_FLAGS}")
endif()
# We need readline to compile
# We need readline to compile
find_package(Readline REQUIRED)
#Collect the source files
@ -65,12 +65,14 @@ if (ENABLE_VPR_GRAPHIC_CXX_FLAG)
libarchfpga
X11
libvtrutil
readline)
else ()
readline
libini)
else ()
target_link_libraries(libvpr
libarchfpga
libvtrutil
readline)
readline
libini)
endif()
#Create the executables

View File

@ -0,0 +1,85 @@
/***********************************/
/* Synthesizable Verilog Dumping */
/* Xifan TANG, EPFL/LSI */
/***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#include <map>
#define MINI_CASE_SENSITIVE
#include "ini.h"
/* Include vpr structs*/
#include "util.h"
#include "physical_types.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph.h"
#include "vpr_utils.h"
#include "path_delay.h"
#include "stats.h"
/* Include FPGA-SPICE utils */
#include "linkedlist.h"
#include "fpga_x2p_utils.h"
#include "fpga_x2p_globals.h"
/* Include verilog utils */
#include "verilog_global.h"
#include "verilog_utils.h"
#include "simulation_info_writer.h"
// Infile Function
static float get_verilog_modelsim_simulation_time_period(const float &time_unit,
const int &num_prog_clock_cycles,
const float &prog_clock_period,
const int &num_op_clock_cycles,
const float &op_clock_period)
{
float total_time_period = 0.;
/* Take into account the prog_reset and reset cycles */
total_time_period = (num_prog_clock_cycles + 2) * prog_clock_period + num_op_clock_cycles * op_clock_period;
total_time_period = total_time_period / time_unit;
return total_time_period;
}
/***** Top-level function *****/
void print_verilog_simulation_info(const int &num_operating_clock_cycles,
const std::string &verilog_dir_formatted,
const std::string &chomped_circuit_name,
const std::string &src_dir_path,
const size_t &num_program_clock_cycles,
const float &prog_clock_freq,
const float &op_clock_freq)
{
mINI::INIStructure ini;
// std::map<char, int> units_map;
// units_map['s']=1; // units_map['ms']=1E-3; // units_map['us']=1E-6;
// units_map['ns']=1E-9; // units_map['ps']=1E-12; // units_map['fs']=1E-15;
/* Compute simulation time period */
float simulation_time_period = get_verilog_modelsim_simulation_time_period(1E-3,
num_program_clock_cycles,
1. / prog_clock_freq,
num_operating_clock_cycles,
1. / op_clock_freq);
ini["SIMULATION_DECK"]["PROJECTNAME "] = "ModelSimProject";
ini["SIMULATION_DECK"]["BENCHMARK "] = chomped_circuit_name;
ini["SIMULATION_DECK"]["TOP_TB"] = chomped_circuit_name + std::string("_top_formal_verification_random_tb");
ini["SIMULATION_DECK"]["SIMTIME "] = std::to_string(simulation_time_period);
ini["SIMULATION_DECK"]["UNIT "] = "ms";
ini["SIMULATION_DECK"]["VERILOG_PATH "] = std::string(src_dir_path);
ini["SIMULATION_DECK"]["VERILOG_FILE1"] = std::string(defines_verilog_file_name);
ini["SIMULATION_DECK"]["VERILOG_FILE2"] = std::string(chomped_circuit_name + "_include_netlists.v");
mINI::INIFile file("SimulationDeckInfo.ini");
file.generate(ini, true);
}

View File

@ -0,0 +1,13 @@
#ifndef VPR_API_H
#define VPR_API_H
#include <string>
void print_verilog_simulation_info(const int &num_operating_clock_cycles,
const std::string &verilog_dir_formatted,
const std::string &chomped_circuit_name,
const std::string &src_dir_path,
const size_t &num_program_clock_cycles,
const float &prog_clock_freq,
const float &op_clock_freq);
#endif

View File

@ -62,6 +62,7 @@
#include "verilog_formality_autodeck.h"
#include "verilog_sdc_pb_types.h"
#include "verilog_include_netlists.h"
#include "simulation_info_writer.h"
#include "verilog_api.h"
@ -410,12 +411,12 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
dump_verilog_formal_verification_top_netlist(sram_verilog_orgz_info, chomped_circuit_name,
std::string(formal_verification_top_netlist_file_path + std::string(".bak")).c_str(), src_dir_path);
/* TODO: new function: to be tested */
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
print_verilog_preconfig_top_module(module_manager, bitstream_manager,
Arch.spice->circuit_lib, global_ports, L_logical_blocks,
device_size, L_grids, L_blocks,
device_size, L_grids, L_blocks,
std::string(chomped_circuit_name), formal_verification_top_netlist_file_path,
std::string(src_dir_path));
std::string(src_dir_path));
/* Output script for formality */
write_formality_script(vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts,
fm_dir_path,
@ -430,6 +431,13 @@ void vpr_fpga_verilog(ModuleManager& module_manager,
print_verilog_random_top_testbench(std::string(chomped_circuit_name), random_top_testbench_file_path,
std::string(src_dir_path), L_logical_blocks,
vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts, Arch.spice->spice_params);
print_verilog_simulation_info(Arch.spice->spice_params.meas_params.sim_num_clock_cycle,
std::string(msim_dir_path),
std::string(chomped_circuit_name),
std::string(src_dir_path),
bitstream_manager.bits().size(),
Arch.spice->spice_params.stimulate_params.prog_clock_freq,
Arch.spice->spice_params.stimulate_params.op_clock_freq);
}
if (TRUE == vpr_setup.FPGA_SPICE_Opts.SynVerilogOpts.print_autocheck_top_testbench) {

View File

@ -10,6 +10,8 @@
#include <assert.h>
#include <sys/stat.h>
#include <unistd.h>
#define MINI_CASE_SENSITIVE
#include "ini.h"
/* Include vpr structs*/
#include "util.h"
@ -39,82 +41,81 @@
#include "verilog_routing.h"
#include "verilog_tcl_utils.h"
static void searching_used_latch(FILE *fp, t_pb *pb, int pb_index, char *chomped_circuit_name, char *inst_name)
{
mINI::INIStructure ini;
static void searching_used_latch(FILE *fp, t_pb * pb, int pb_index, char* chomped_circuit_name, char* inst_name){
int i, j;
// char* tmp = NULL;
char WriteBuffer[200];
char INI_lbl[100];
// char* tmp = NULL;
const t_pb_type *pb_type;
t_mode *mode;
t_pb_graph_node *node;
// char* index = NULL;
t_pb_graph_node * node;
// char* index = NULL;
pb_type = pb->pb_graph_node->pb_type;
node = pb->pb_graph_node->physical_pb_graph_node;
mode = &pb_type->modes[pb->mode];
// tmp = (char*) my_malloc(sizeof(1 + (strlen(ff_hierarchy) + 1 + strlen(my_strcat(pb_type->name, index)))));
// tmp = ff_hierarchy;
// index = my_strcat("_", my_strcat(my_itoa(pb_index), "_"));
// tmp = (char*) my_malloc(sizeof(1 + (strlen(ff_hierarchy) + 1 + strlen(my_strcat(pb_type->name, index)))));
// tmp = ff_hierarchy;
// index = my_strcat("_", my_strcat(my_itoa(pb_index), "_"));
if (pb_type->num_modes > 0)
{
for (i = 0; i < mode->num_pb_type_children; i++)
{
for (j = 0; j < mode->pb_type_children[i].num_pb; j++)
{
// if(strcmp(pb_type->name, mode->name) != 0)
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->name, index)));
if (pb->child_pbs[i][j].name != NULL)
if (pb_type->num_modes > 0) {
for (i = 0; i < mode->num_pb_type_children; i++) {
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
// if(strcmp(pb_type->name, mode->name) != 0)
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->name, index)));
if(pb->child_pbs[i][j].name != NULL)
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
}
}
}
else if ((pb_type->class_type == LATCH_CLASS) && (pb->name))
{
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->physical_pb_type_name, my_strcat(index, "/dff_0_"))));
} else if((pb_type->class_type == LATCH_CLASS) && (pb->name)){
// tmp = my_strcat(tmp, my_strcat("/", my_strcat(pb_type->physical_pb_type_name, my_strcat(index, "/dff_0_"))));
fprintf(fp, "set_user_match r:/WORK/%s/%s_reg i:/WORK/%s/%sdff_0 -type cell -noninverted\n", chomped_circuit_name,
pb->name,
inst_name,
gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node));
pb->name,
inst_name,
gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node) );
sprintf(WriteBuffer, "%s/%sdff_0 ",
inst_name, gen_verilog_one_pb_graph_node_full_name_in_hierarchy(node));
sprintf(INI_lbl, "%s_reg", pb->name);
ini["REGISTER_MATCH"][INI_lbl] = WriteBuffer;
}
//free(tmp); //Looks like is the cause of a double free, once free executated next iteration as no value in tmp
return;
}
static void clb_iteration(FILE *fp, char *chomped_circuit_name, int h)
{
t_pb *pb;
char *inst_name = NULL;
static void clb_iteration(FILE *fp, char* chomped_circuit_name, int h){
t_pb* pb;
char* inst_name = NULL;
const t_pb_type *pb_type;
t_mode *mode;
int i, j, x_pos, y_pos;
char *grid_x = NULL;
char *grid_y = NULL;
char* grid_x = NULL;
char* grid_y = NULL;
x_pos = block[h].x;
y_pos = block[h].y;
pb = (t_pb *)block[h].pb;
pb = (t_pb*) block[h].pb;
pb_type = pb->pb_graph_node->pb_type;
mode = &pb_type->modes[pb->mode];
grid_x = my_strcat("_", my_strcat(my_itoa(x_pos), "_"));
grid_x = my_strcat("_", my_strcat(my_itoa(x_pos), "_"));
grid_y = my_strcat("_", my_strcat(my_itoa(y_pos), "_"));
if (strcmp(pb_type->name, FILL_TYPE->name) == 0)
{
inst_name = my_strcat(chomped_circuit_name, my_strcat(formal_verification_top_postfix, my_strcat("/", my_strcat(formal_verification_top_module_uut_name, my_strcat("/grid", my_strcat(grid_x, my_strcat(grid_y, "/")))))));
if (pb_type->num_modes > 0)
{
for (i = 0; i < mode->num_pb_type_children; i++)
{
if (strcmp(pb_type->name, FILL_TYPE->name) == 0) {
inst_name = my_strcat(chomped_circuit_name, my_strcat(formal_verification_top_postfix, my_strcat("/", my_strcat(formal_verification_top_module_uut_name, my_strcat("/grid",my_strcat(grid_x, my_strcat(grid_y, "/" )))))));
if (pb_type->num_modes > 0) {
for (i = 0; i < mode->num_pb_type_children; i++) {
inst_name = my_strcat(inst_name, my_strcat("grid_", my_strcat(pb_type->name, my_strcat("_", my_strcat(my_itoa(i), "_")))));
for (j = 0; j < mode->pb_type_children[i].num_pb; j++)
{
for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
/* If child pb is not used but routing is used, I must print things differently */
if ((pb->child_pbs[i] != NULL) && (pb->child_pbs[i][j].name != NULL))
{
if ((pb->child_pbs[i] != NULL)
&& (pb->child_pbs[i][j].name != NULL)) {
searching_used_latch(fp, &pb->child_pbs[i][j], j, chomped_circuit_name, inst_name);
}
}
@ -124,14 +125,29 @@ static void clb_iteration(FILE *fp, char *chomped_circuit_name, int h)
return;
}
static void formality_include_user_defined_verilog_netlists(FILE *fp,
t_spice spice)
{
static void match_registers(FILE *fp, char* chomped_circuit_name) {
int h;
for(h = 0; h < copy_nb_clusters; h++)
clb_iteration(fp, chomped_circuit_name, h);
/* for(h = 0; h < copy_nb_clusters; h++){
free_cb(copy_clb[h].pb);
free(copy_clb[h].name);
free(copy_clb[h].nets);
free(copy_clb[h].pb);
}*/
// free(copy_clb);
// free(block);
return;
}
static
void formality_include_user_defined_verilog_netlists(FILE* fp,
t_spice spice) {
int i;
/* A valid file handler*/
if (NULL == fp)
{
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(File:%s, [LINE%d])Invalid File Handler!\n",
__FILE__, __LINE__);
@ -139,16 +155,12 @@ static void formality_include_user_defined_verilog_netlists(FILE *fp,
}
/* Include user-defined sub-circuit netlist */
for (i = 0; i < spice.num_include_netlist; i++)
{
if (0 == spice.include_netlists[i].included)
{
for (i = 0; i < spice.num_include_netlist; i++) {
if (0 == spice.include_netlists[i].included) {
assert(NULL != spice.include_netlists[i].path);
fprintf(fp, "%s \n", spice.include_netlists[i].path);
fprintf(fp, "%s ", spice.include_netlists[i].path);
spice.include_netlists[i].included = 1;
}
else
{
} else {
assert(1 == spice.include_netlists[i].included);
}
}
@ -156,102 +168,148 @@ static void formality_include_user_defined_verilog_netlists(FILE *fp,
return;
}
void write_formality_script(t_syn_verilog_opts fpga_verilog_opts,
char *fm_dir_formatted,
char *src_dir_formatted,
char *chomped_circuit_name,
t_spice spice)
{
int iblock, h;
char *formScriptfp = NULL;
char *benchmark_path = NULL;
char *original_output_name = NULL;
/* int output_length; */
/* int pos; */
FILE *fp = NULL;
void write_formality_script (t_syn_verilog_opts fpga_verilog_opts,
char* fm_dir_formatted,
char* src_dir_formatted,
char* chomped_circuit_name,
t_spice spice){
int iblock, i, FileCounter=0;
char* formality_script_file_name = NULL;
char* benchmark_path = NULL;
char* original_output_name = NULL;
char WriteBuffer[200];
char INI_lbl[20];
/* int output_length; */
/* int pos; */
FILE* fp = NULL;
if (TRUE == fpga_verilog_opts.print_autocheck_top_testbench)
{
if(TRUE == fpga_verilog_opts.print_autocheck_top_testbench)
benchmark_path = fpga_verilog_opts.reference_verilog_benchmark_file;
}
else
{
benchmark_path = "Insert verilog benchmark path";
}
formScriptfp = my_strcat(fm_dir_formatted,
my_strcat(chomped_circuit_name,
formality_script_name_postfix));
fp = fopen(formScriptfp, "w");
if (NULL == fp)
{
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Failure in create formality script %s",
__FILE__, __LINE__, formScriptfp);
exit(1);
}
formality_script_file_name = my_strcat(fm_dir_formatted, my_strcat(chomped_circuit_name, formality_script_name_postfix));
fp = fopen(formality_script_file_name, "w");
if (NULL == fp) {
vpr_printf(TIO_MESSAGE_ERROR,
"(FILE:%s,LINE[%d])Failure in create formality script %s",
__FILE__, __LINE__, formality_script_file_name);
exit(1);
}
/* Load Verilog benchmark as reference */
fprintf(fp, "%s\n\n", benchmark_path);
fprintf(fp, "read_verilog -container r -libname WORK -05 { %s }\n", benchmark_path);
ini["BENCHMARK_INFO"]["benchmark_netlist "] = benchmark_path;
/* Set reference top */
fprintf(fp, "%s\n\n", chomped_circuit_name);
fprintf(fp, "set_top r:/WORK/%s\n", chomped_circuit_name);
ini["BENCHMARK_INFO"]["src_top_module "] = chomped_circuit_name;
/* Load generated verilog as implemnetation */
fprintf(fp, "%s%s%s\n", src_dir_formatted, chomped_circuit_name,
fprintf(fp, "read_verilog -container i -libname WORK -05 { ");
fprintf(fp, "%s%s%s ", src_dir_formatted,
chomped_circuit_name,
verilog_top_postfix);
sprintf(WriteBuffer, "%s%s%s", src_dir_formatted, chomped_circuit_name,
verilog_top_postfix);
sprintf(INI_lbl, "impl_netlist_%02d",FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
fprintf(fp, "%s%s%s\n", src_dir_formatted,
chomped_circuit_name,
formal_verification_verilog_file_postfix);
fprintf(fp, "%s%s%s ", src_dir_formatted,
chomped_circuit_name,
formal_verification_verilog_file_postfix);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
chomped_circuit_name, formal_verification_verilog_file_postfix);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
init_include_user_defined_verilog_netlists(spice);
formality_include_user_defined_verilog_netlists(fp, spice);
fprintf(fp, "%s%s%s\n", src_dir_formatted,
default_rr_dir_name,
routing_verilog_file_name);
fprintf(fp, "%s%s%s\n", src_dir_formatted,
default_lb_dir_name,
logic_block_verilog_file_name);
fprintf(fp, "%s%s%s\n", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
fprintf(fp, "\n");
// formality_include_user_defined_verilog_netlists(fp, spice);
/* Set implementation top */
fprintf(fp, "%s\n", my_strcat(chomped_circuit_name, formal_verification_top_postfix));
/* Run matching */
fprintf(fp, "\n");
/* Add manual matching for the outputs */
for (iblock = 0; iblock < num_logical_blocks; iblock++)
{
original_output_name = NULL;
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model)
{
/* Make sure We find the correct logical block !*/
assert((VPACK_INPAD == logical_block[iblock].type) || (VPACK_OUTPAD == logical_block[iblock].type));
if (VPACK_OUTPAD == logical_block[iblock].type)
{
/* output_length = strlen(logical_block[iblock].name); */
original_output_name = logical_block[iblock].name + 4;
/* printf("%s", original_output_name); */
// fprintf(fp, "set_user_match r:/WORK/%s/%s i:/WORK/%s/%s[0] -type port -noninverted\n",
fprintf(fp, "/WORK/%s/%s /WORK/%s/%s[0]\n",
chomped_circuit_name,
original_output_name,
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
my_strcat(logical_block[iblock].name, formal_verification_top_module_port_postfix));
}
/* Include user-defined sub-circuit netlist */
for (i = 0; i < spice.num_include_netlist; i++) {
if (0 == spice.include_netlists[i].included) {
assert(NULL != spice.include_netlists[i].path);
fprintf(fp, "%s ", spice.include_netlists[i].path);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = spice.include_netlists[i].path;
spice.include_netlists[i].included = 1;
} else {
assert(1 == spice.include_netlists[i].included);
}
}
for (h = 0; h < copy_nb_clusters; h++)
clb_iteration(fp, chomped_circuit_name, h);
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_rr_dir_name,
routing_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_rr_dir_name,
routing_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_lb_dir_name,
logic_block_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_lb_dir_name,
logic_block_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fprintf(fp, "%s%s%s ", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
sprintf(WriteBuffer, "%s%s%s\n", src_dir_formatted,
default_submodule_dir_name,
submodule_verilog_file_name);
sprintf(INI_lbl, "impl_netlist_%02d", FileCounter++);
ini["FPGA_INFO"][INI_lbl] = WriteBuffer;
fprintf(fp, "}\n");
/* Set implementation top */
fprintf(fp, "set_top i:/WORK/%s\n", my_strcat(chomped_circuit_name,
formal_verification_top_postfix));
sprintf(WriteBuffer, "%s", my_strcat(chomped_circuit_name,
formal_verification_top_postfix));
ini["FPGA_INFO"]["impl_top_module"] = WriteBuffer;
/* Run matching */
fprintf(fp, "match\n");
/* Add manual matching for the outputs */
for (iblock = 0; iblock < num_logical_blocks; iblock++) {
original_output_name = NULL;
if (iopad_verilog_model == logical_block[iblock].mapped_spice_model) {
/* Make sure We find the correct logical block !*/
assert((VPACK_INPAD == logical_block[iblock].type)
||(VPACK_OUTPAD == logical_block[iblock].type));
if(VPACK_OUTPAD == logical_block[iblock].type){
/* output_length = strlen(logical_block[iblock].name); */
original_output_name = logical_block[iblock].name + 4;
/* printf("%s", original_output_name); */
fprintf(fp, "set_user_match r:/WORK/%s/%s i:/WORK/%s/%s[0] -type port -noninverted\n",
chomped_circuit_name,
original_output_name,
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
my_strcat(logical_block[iblock].name,
formal_verification_top_module_port_postfix));
sprintf(WriteBuffer, "%s/%s[0]",
my_strcat(chomped_circuit_name, formal_verification_top_postfix),
my_strcat(logical_block[iblock].name, formal_verification_top_module_port_postfix));
sprintf(INI_lbl, "%s", original_output_name);
ini["PORT_MATCHING"][INI_lbl] = WriteBuffer;
}
}
}
match_registers(fp, chomped_circuit_name);
/* Run verification */
fprintf(fp, "\n");
fprintf(fp, "verify\n");
/* Script END */
fclose(fp);
mINI::INIFile file(my_strcat(formality_script_file_name,".ini"));
file.generate(ini, true);
return;
}