write_verilog
This commit is contained in:
parent
d9237aa3e5
commit
3f7e207491
|
|
@ -210,6 +210,7 @@ set(STA_SOURCE
|
|||
verilog/VerilogReader.cc
|
||||
verilog/VerilogLex.cc
|
||||
verilog/VerilogParse.cc
|
||||
verilog/VerilogWriter.cc
|
||||
)
|
||||
|
||||
set(STA_HEADERS
|
||||
|
|
@ -385,6 +386,7 @@ set(STA_HEADERS
|
|||
|
||||
verilog/Verilog.hh
|
||||
verilog/VerilogReader.hh
|
||||
verilog/VerilogWriter.hh
|
||||
)
|
||||
|
||||
# Source files.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "VerilogReader.hh"
|
||||
#include "VerilogWriter.hh"
|
||||
#include "Sta.hh"
|
||||
|
||||
using sta::Sta;
|
||||
|
|
@ -48,4 +49,12 @@ delete_verilog_reader()
|
|||
deleteVerilogReader();
|
||||
}
|
||||
|
||||
void
|
||||
write_verilog_cmd(const char *filename,
|
||||
bool sorted)
|
||||
{
|
||||
Network *network = cmdNetwork();
|
||||
writeVerilog(filename, sorted, network);
|
||||
}
|
||||
|
||||
%} // inline
|
||||
|
|
|
|||
|
|
@ -19,5 +19,16 @@ namespace eval sta {
|
|||
# Defined by SWIG interface Verilog.i.
|
||||
define_cmd_args "read_verilog" {filename}
|
||||
|
||||
define_cmd_args "write_verilog" {[-sorted] filename}
|
||||
|
||||
proc write_verilog { args } {
|
||||
parse_key_args "write_verilog" args keys {} flags {-sorted}
|
||||
|
||||
set sorted [info exists flags(-sorted)]
|
||||
check_argc_eq1 "write_verilog" $args
|
||||
set filename $args
|
||||
write_verilog_cmd $filename $sorted
|
||||
}
|
||||
|
||||
# sta namespace end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,212 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2019, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "Machine.hh"
|
||||
#include "Error.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "NetworkCmp.hh"
|
||||
#include "VerilogNamespace.hh"
|
||||
#include "VerilogWriter.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class VerilogWriter
|
||||
{
|
||||
public:
|
||||
VerilogWriter(const char *filename,
|
||||
bool sorted,
|
||||
FILE *stream,
|
||||
Network *network);
|
||||
void writeModule(Instance *inst);
|
||||
|
||||
protected:
|
||||
void writePorts(Cell *cell);
|
||||
void writePortDcls(Cell *cell);
|
||||
const char *verilogPortDir(PortDirection *dir);
|
||||
void writeChildren(Instance *inst);
|
||||
void writeChild(Instance *child);
|
||||
|
||||
const char *filename_;
|
||||
bool sorted_;
|
||||
FILE *stream_;
|
||||
Network *network_;
|
||||
|
||||
Set<Cell*> written_cells_;
|
||||
Set<Instance*> pending_children_;
|
||||
};
|
||||
|
||||
void
|
||||
writeVerilog(const char *filename,
|
||||
bool sorted,
|
||||
Network *network)
|
||||
{
|
||||
FILE *stream = fopen(filename, "w");
|
||||
if (stream) {
|
||||
VerilogWriter writer(filename, sorted, stream, network);
|
||||
writer.writeModule(network->topInstance());
|
||||
fclose(stream);
|
||||
}
|
||||
else
|
||||
throw FileNotWritable(filename);
|
||||
}
|
||||
|
||||
VerilogWriter::VerilogWriter(const char *filename,
|
||||
bool sorted,
|
||||
FILE *stream,
|
||||
Network *network) :
|
||||
filename_(filename),
|
||||
sorted_(sorted),
|
||||
stream_(stream),
|
||||
network_(network)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeModule(Instance *inst)
|
||||
{
|
||||
Cell *cell = network_->cell(inst);
|
||||
fprintf(stream_, "module %s (",
|
||||
network_->name(cell));
|
||||
writePorts(cell);
|
||||
writePortDcls(cell);
|
||||
fprintf(stream_, "\n");
|
||||
writeChildren(inst);
|
||||
fprintf(stream_, "endmodule\n");
|
||||
written_cells_.insert(cell);
|
||||
|
||||
for (auto child : pending_children_) {
|
||||
Cell *child_cell = network_->cell(child);
|
||||
if (!written_cells_.hasKey(child_cell))
|
||||
writeModule(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writePorts(Cell *cell)
|
||||
{
|
||||
bool first = true;
|
||||
CellPortIterator *port_iter = network_->portIterator(cell);
|
||||
while (port_iter->hasNext()) {
|
||||
Port *port = port_iter->next();
|
||||
if (!first)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, "%s",
|
||||
network_->name(port));
|
||||
first = false;
|
||||
}
|
||||
delete port_iter;
|
||||
fprintf(stream_, ");\n");
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writePortDcls(Cell *cell)
|
||||
{
|
||||
CellPortIterator *port_iter = network_->portIterator(cell);
|
||||
while (port_iter->hasNext()) {
|
||||
Port *port = port_iter->next();
|
||||
PortDirection *dir = network_->direction(port);
|
||||
if (dir) {
|
||||
fprintf(stream_, " %s",
|
||||
verilogPortDir(dir));
|
||||
if (network_->isBus(port))
|
||||
fprintf(stream_, " [%d:%d]",
|
||||
network_->fromIndex(port),
|
||||
network_->toIndex(port));
|
||||
fprintf(stream_, " %s;\n",
|
||||
network_->name(port));
|
||||
if (dir->isTristate()) {
|
||||
fprintf(stream_, " tri");
|
||||
if (network_->isBus(port))
|
||||
fprintf(stream_, " [%d:%d]",
|
||||
network_->fromIndex(port),
|
||||
network_->toIndex(port));
|
||||
fprintf(stream_, " %s;\n",
|
||||
network_->name(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
delete port_iter;
|
||||
}
|
||||
|
||||
const char *
|
||||
VerilogWriter::verilogPortDir(PortDirection *dir)
|
||||
{
|
||||
if (dir == PortDirection::input())
|
||||
return "input";
|
||||
else if (dir == PortDirection::output())
|
||||
return "output";
|
||||
else if (dir == PortDirection::bidirect())
|
||||
return "inout";
|
||||
else if (dir == PortDirection::tristate())
|
||||
return "output";
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeChildren(Instance *inst)
|
||||
{
|
||||
Vector<Instance*> children;
|
||||
InstanceChildIterator *child_iter = network_->childIterator(inst);
|
||||
while (child_iter->hasNext()) {
|
||||
Instance *child = child_iter->next();
|
||||
children.push_back(child);
|
||||
if (network_->isHierarchical(child))
|
||||
pending_children_.insert(child);
|
||||
}
|
||||
delete child_iter;
|
||||
|
||||
if (sorted_)
|
||||
sort(children, InstancePathNameLess(network_));
|
||||
|
||||
for (auto child : children)
|
||||
writeChild(child);
|
||||
}
|
||||
|
||||
void
|
||||
VerilogWriter::writeChild(Instance *child)
|
||||
{
|
||||
Cell *child_cell = network_->cell(child);
|
||||
const char *child_name = network_->name(child);
|
||||
const char *child_vname = instanceVerilogName(child_name, '\0');
|
||||
fprintf(stream_, " %s %s (",
|
||||
network_->name(child_cell),
|
||||
child_vname);
|
||||
bool first = true;
|
||||
InstancePinIterator *pin_iter = network_->pinIterator(child);
|
||||
while (pin_iter->hasNext()) {
|
||||
Pin *pin = pin_iter->next();
|
||||
Net *net = network_->net(pin);
|
||||
if (net) {
|
||||
const char *net_name = network_->name(net);
|
||||
const char *net_vname = netVerilogName(net_name, '\0');
|
||||
Port *port = network_->port(pin);
|
||||
const char *port_name = network_->name(port);
|
||||
if (!first)
|
||||
fprintf(stream_, ",\n ");
|
||||
fprintf(stream_, ".%s(%s)",
|
||||
port_name,
|
||||
net_vname);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
delete pin_iter;
|
||||
fprintf(stream_, ");\n");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2019, Parallax Software, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef STA_WRITE_VERILOG_H
|
||||
#define STA_WRITE_VERILOG_H
|
||||
|
||||
namespace sta {
|
||||
|
||||
class Network;
|
||||
|
||||
void
|
||||
writeVerilog(const char *filename,
|
||||
bool sorted,
|
||||
Network *network);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue