Commit f3b3e75e by lvzhengyang

add verilog parser

parent e800cd98
add_subdirectory(src/parsers)
include("swig_lib")
swig_lib(NAME db_mgr
......@@ -23,5 +25,6 @@ target_link_libraries(db_mgr
PUBLIC
odb
utl
PRIVATE
db_mgr_verilog_parser
)
......@@ -22,12 +22,14 @@ class Logger;
namespace eda {
namespace db_mgr {
class VParser;
/* DB Manager: for hierarchical design. A hierarchical design
* contains multiple sub-block within the 'top' module. Because
* dbBlock class in OpenDB only supports two-levels of hierarchy,
* I choose to use a dbDatabase to represent a Block.
*
* NOTE: OpenDB claims that it supports that a dbDataBase can
* NOTE: OpenDB claims that it supports that a dbDatabase can
* store multiple dbChip, but denote with "DEPRECATE".
*
* A hierarchical design:
......@@ -53,14 +55,19 @@ public:
bool isTech=false,
bool isLib=true);
bool haveBlockDB(const std::string block);
bool createBlockDB(const char* block_name);
odb::dbDatabase* findBlockDB(const char* db_name);
odb::dbDatabase* createBlockDB(const char* block_name);
bool deleteBlockDB(const char* block_name);
bool readBlockDef(const char* block_name,
const char* def_file,
bool cont_on_err,
bool is_floorplan,
bool is_incr); // incr: incremental
bool readVerilog(const char* design_name,
const char* v_file);
void setCurrentBlock(const char* design);
void setCurrentBlock(odb::dbDatabase* db);
void setLogger(utl::Logger* logger);
void init(utl::Logger* logger);
......@@ -77,13 +84,17 @@ private:
* blocks.
*/
std::unordered_map<std::string, odb::dbDatabase*> block_dbs_;
odb::dbDatabase* current_block_db_;
utl::Logger* logger_;
/* parsers */
// use OpenDB's lef/def parser
// TODO: Wrap the LEF/DEF parsers into class
std::unique_ptr<odb::lefin> lef_parser_;
std::unique_ptr<odb::defin> def_parser_;
// use Limbo's verilog parser
std::unique_ptr<VParser> verilog_parser_;
};
} // namespace db_mgr
......
......@@ -3,6 +3,7 @@
#include "lefin.h"
#include "defin.h"
#include "utl/Logger.h"
#include "verilog_parser.h"
namespace eda {
namespace db_mgr {
......@@ -11,7 +12,9 @@ DbMgr::DbMgr()
: lib_db_(nullptr),
logger_(nullptr),
lef_parser_(nullptr),
def_parser_(nullptr)
def_parser_(nullptr),
verilog_parser_(nullptr),
current_block_db_(nullptr)
{
block_dbs_.clear();
}
......@@ -21,6 +24,9 @@ void DbMgr::init(utl::Logger* logger)
setLogger(logger);
lib_db_ = odb::dbDatabase::create();
lef_parser_ = std::make_unique<odb::lefin>(lib_db_, logger_, false);
// def_parser_
verilog_parser_ = std::make_unique<VParser>();
verilog_parser_->setLogger(logger_);
}
DbMgr::~DbMgr()
......@@ -35,6 +41,7 @@ DbMgr::~DbMgr()
}
block_dbs_.clear();
}
current_block_db_ = nullptr;
}
bool DbMgr::haveBlockDB(const std::string block)
......@@ -48,6 +55,22 @@ void DbMgr::setLogger(utl::Logger* logger)
logger_ = logger;
}
void DbMgr::setCurrentBlock(odb::dbDatabase* db)
{
if (db == nullptr) {
logger_->error(utl::MGR, 101, "Failed to set current block.");
return;
}
current_block_db_ = db;
logger_->info(utl::MGR, 11, "Current Block is {}.",
db->getChip()->getBlock()->getConstName());
}
void DbMgr::setCurrentBlock(const char* design_name)
{
setCurrentBlock(findBlockDB(design_name));
}
bool DbMgr::readLibDB(const char* lef_path, const char* libname,
bool isTech, bool isLib)
{
......@@ -66,17 +89,26 @@ bool DbMgr::readLibDB(const char* lef_path, const char* libname,
return true;
}
bool DbMgr::createBlockDB(const char* block_name)
odb::dbDatabase* DbMgr::createBlockDB(const char* block_name)
{
if (haveBlockDB(block_name)) {
logger_->error(utl::MGR, 2, "Cannot create existing block: {}", block_name);
return false;
return nullptr;
}
odb::dbDatabase* block_db = odb::dbDatabase::duplicate(lib_db_);
block_dbs_.emplace(std::make_pair(block_name, block_db));
logger_->info(utl::MGR, 3, "Create Block: {}. Ensure lib has been successfully read.",
block_name);
return true;
odb::dbChip* chip = odb::dbChip::create(block_db);
if (chip == nullptr) {
logger_->error(utl::MGR, 5, "Cannot create dbChip for Block DB: {}", block_name);
} else {
char hier_delimeter = '/';
if (!odb::dbBlock::create(chip, block_name, hier_delimeter)) {
logger_->error(utl::MGR, 6, "Cannot create dbBlock for Block DB: {}", block_name);
}
}
return block_db;
}
bool DbMgr::deleteBlockDB(const char* block_name)
......@@ -93,6 +125,12 @@ bool DbMgr::deleteBlockDB(const char* block_name)
return true;
}
odb::dbDatabase* DbMgr::findBlockDB(const char* db_name)
{
if (!haveBlockDB(db_name)) return nullptr;
return block_dbs_.find(db_name)->second;
}
bool DbMgr::readBlockDef(const char* block_name,
const char* def_file,
bool cont_on_err,
......@@ -170,5 +208,24 @@ bool DbMgr::readBlockDef(const char* block_name,
return true;
}
bool DbMgr::readVerilog(const char* design_name,
const char* v_file)
{
if (design_name != nullptr) {
if (haveBlockDB(design_name)) {
setCurrentBlock(design_name);
} else {
setCurrentBlock(createBlockDB(design_name));
}
} else {
if (current_block_db_ == nullptr) {
logger_->error(utl::MGR, 102, "Failed to read verilog, no block set.");
return false;
}
}
verilog_parser_->setOdb(current_block_db_);
return verilog_parser_->read(design_name, v_file);
}
} // namespace db_mgr
} // namespace eda
......@@ -36,6 +36,11 @@ bool delete_blk_db(const char* block_name)
return getDbMgr()->deleteBlockDB(block_name);
}
bool read_verilog(const char* design, const char* v_file)
{
return getDbMgr()->readVerilog(design, v_file);
}
} // namespace db_mgr
%} // inline
......@@ -48,4 +48,18 @@ proc delete_block { args } {
foreach block $args {
db_mgr::delete_blk_db $block
}
}
\ No newline at end of file
}
define_cmd_args "read_verilog" { [-design]\
v_file \
}
proc read_verilog { args } {
parse_key_args "read_verilog" args keys {-design} flags {}
set design ""
if { info exists keys(-design) } {
set design $keys(-design)
}
set filename [file nativename [lindex $args 0]]
db_mgr::read_verilog $design $filename
}
add_subdirectory(verilog_parser)
add_library(db_mgr_verilog_parser)
target_sources(db_mgr_verilog_parser
PRIVATE
./verilog_database.cpp
./verilog_parser.cpp
)
target_include_directories(db_mgr_verilog_parser
PUBLIC
./
${LIMBO_HOME}/limbo/parsers/verilog/bison
)
target_link_libraries(db_mgr_verilog_parser
PUBLIC
odb
PRIVATE
verilogparser # built in thirdparty Limbo
Boost::boost
)
#include "verilog_database.h"
#include "db.h"
#include "utl/Logger.h"
namespace eda {
namespace db_mgr {
VDb::VDb()
: odb_(nullptr),
current_module_(nullptr),
current_block_(nullptr),
logger_(nullptr)
{}
VDb::VDb(odb::dbDatabase* odb)
{
odb_ = odb;
current_block_ = odb_->getChip()->getBlock();
}
VDb::~VDb()
{
odb_ = nullptr; // leave the free job of odb to db_mgr
current_module_ = nullptr;
}
/*
bool VDb::read(const std::string& design_name,
const std::string& v_file)
{
if (current_block_->getConstName() != design_name) {
return false;
}
return VerilogParser::read(*this, v_file);
}
*/
void VDb::setOdb(odb::dbDatabase* odb)
{
odb_ = odb;
}
void VDb::setLogger(utl::Logger* logger)
{
logger_ = logger;
}
void VDb::verilog_module_declaration_cbk(
std::string const& moduleName,
std::vector<VerilogParser::GeneralName> const& vPinName)
{
// create top module
const char* module_name = moduleName.c_str();
current_module_ = odb::dbModule::create(current_block_, module_name);
if (current_module_) {
logger_->info(utl::MGR, 200, "Create module: {}", module_name);
} else {
logger_->warn(utl::MGR, 200, "Failed to create module: {}", module_name);
}
}
void VDb::verilog_net_declare_cbk(
std::string const& netName,
VerilogParser::Range const& range)
{
const char* net_name = netName.c_str();
if (range.low == range.high) {
if (!odb::dbNet::create(current_block_, net_name)) {
logger_->warn(utl::MGR, 201, "Failed to create net: {}", net_name);
}
} else {
for (int i = range.low; i <= range.high; i++) {
std::string netName_i = netName + "[" + std::to_string(i) + "]";
const char* net_name_i = netName_i.c_str();
if (!odb::dbNet::create(current_block_, net_name_i)) {
logger_->warn(utl::MGR, 201, "Failed to create net: {}", net_name_i);
}
}
}
}
void VDb::verilog_pin_declare_cbk(
std::string const& pinName,
unsigned type,
VerilogParser::Range const& range)
{
std::string direction;
switch(type) {
case VerilogParser::PinType::kINPUT:
direction = "INPUT";
break;
case VerilogParser::PinType::kOUTPUT:
direction = "OUTPUT";
break;
case VerilogParser::PinType::kREG:
direction = "REG";
break;
default:
direction = "UNDEFINED";
break;
}
const char* pin_name = pinName.c_str();
if (range.low == range.high) {
if (!odb::dbLogicPort::create(current_block_, pin_name, direction)) {
logger_->warn(utl::MGR, 202, "Failed to create logic pin: {}", pin_name);
}
} else {
for (int i = range.low; i <= range.high; i++) {
std::string pinName_i = pinName + "[" + std::to_string(i) + "]";
const char* pin_name_i = pinName_i.c_str();
if (!odb::dbLogicPort::create(current_block_, pin_name_i, direction)) {
logger_->warn(utl::MGR, 202, "Failed to create logic pin: {}", pin_name_i);
}
}
}
}
void VDb::verilog_instance_cbk(
std::string const& macroName,
std::string const& instName,
std::vector<VerilogParser::NetPin> const& vNetPin)
{
const char* macro_name = macroName.c_str();
odb::dbMaster* master = odb_->findMaster(macro_name);
if (master == nullptr) {
logger_->warn(utl::MGR, 203, "Cannot find master cell: {}", macro_name);
return;
}
const char* inst_name = instName.c_str();
odb::dbInst* inst = odb::dbInst::create(current_block_, master, inst_name);
if (!inst) {
logger_->warn(utl::MGR, 204, "Cannot create inst: {}", inst_name);
return;
}
for (auto& np : vNetPin) {
odb::dbNet* db_net = current_block_->findNet(np.net.c_str());
if (!db_net) {
logger_->warn(utl::MGR, 205, "Cannot find net: {}", np.net.c_str());
continue;
}
odb::dbITerm* iterm = inst->findITerm(np.pin.c_str());
if (!iterm) {
logger_->warn(utl::MGR, 206, "Cannot find Instance Term: {}", np.pin.c_str());
continue;
}
iterm->connect(db_net);
}
}
void VDb::verilog_assignment_cbk(
std::string const& target_name,
VerilogParser::Range const& target_range,
std::string const& source_name,
VerilogParser::Range const& source_range
)
{}
} // namespace db_mgr
} // namespace eda
\ No newline at end of file
#include "VerilogDriver.h"
#include <string>
namespace odb {
class dbDatabase;
class dbModule;
class dbBlock;
}
namespace utl {
class Logger;
}
namespace eda {
namespace db_mgr {
class VDb : public VerilogParser::VerilogDataBase
{
public:
VDb();
VDb(odb::dbDatabase* odb);
~VDb();
/*
bool read(const std::string& design_name,
const std::string& v_file);
*/
void setOdb(odb::dbDatabase* odb);
void setLogger(utl::Logger* logger);
///==== Verilog Callbacks ====
// declared in VerilogDataBase.h
virtual void verilog_module_declaration_cbk(std::string const& module_name,
std::vector<VerilogParser::GeneralName> const& vPinName);
virtual void verilog_net_declare_cbk(std::string const& netName,
VerilogParser::Range const& range);
virtual void verilog_pin_declare_cbk(std::string const& pinName,
unsigned type,
VerilogParser::Range const& range);
virtual void verilog_instance_cbk(std::string const& macroName,
std::string const& instName,
std::vector<VerilogParser::NetPin> const& vNetPin);
virtual void verilog_assignment_cbk(std::string const& target_name,
VerilogParser::Range const& target_range,
std::string const& source_name,
VerilogParser::Range const& source_range);
private:
odb::dbDatabase* odb_; // OpenDB
odb::dbModule* current_module_;
odb::dbBlock* current_block_;
utl::Logger* logger_;
};
}
} // namespace eda
#include "verilog_parser.h"
#include "verilog_database.h"
// #include "VerilogDriver.h"
#include "utl/Logger.h"
#include "db.h"
namespace eda {
namespace db_mgr{
VParser::VParser()
: current_block_(nullptr),
odb_(nullptr),
logger_(nullptr)
{
v_db_ = std::make_unique<VDb>();
}
void VParser::setLogger(utl::Logger* logger)
{
v_db_->setLogger(logger);
logger_ = logger;
}
void VParser::setOdb(odb::dbDatabase* db)
{
v_db_->setOdb(db);
odb_ = db;
if (db != nullptr) {
current_block_ = db->getChip()->getBlock();
}
}
bool VParser::read(std::string const& design_name,
std::string const& v_file)
{
if (current_block_ == nullptr) {
return false;
}
if (current_block_->getConstName() != design_name) {
return false;
}
VDb v_db;
v_db.setLogger(logger_);
v_db.setOdb(odb_);
// return true;
return VerilogParser::read(v_db, v_file);
}
VParser::~VParser()
{}
} // db_mgr
} // eda
\ No newline at end of file
#ifndef _VERILOG_PARSER_H_
#define _VERILOG_PARSER_H_
#include "VerilogDriver.h"
#include <string>
#include <memory>
namespace odb {
class dbDatabase;
class dbBlock;
}
namespace utl {
class Logger;
}
namespace eda {
namespace db_mgr {
class VDb;
class VParser
{
public:
VParser();
~VParser();
bool read(std::string const& design_name,
std::string const& v_file);
void setLogger(utl::Logger* logger);
void setOdb(odb::dbDatabase* db);
private:
std::unique_ptr<VDb> v_db_;
odb::dbBlock* current_block_;
odb::dbDatabase* odb_;
utl::Logger* logger_;
};
} // namsepace db_mgr
} // namsepace eda
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment