degate  0.1.2
Public Types | Public Member Functions | Protected Member Functions
degate::VerilogCodeTemplateGenerator Class Reference

A code template generator for Verilog. More...

#include <VerilogCodeTemplateGenerator.h>

Inheritance diagram for degate::VerilogCodeTemplateGenerator:
Inheritance graph
[legend]

List of all members.

Public Types

typedef std::map< std::string,
std::string > 
port_map_type

Public Member Functions

 VerilogCodeTemplateGenerator (std::string const &entity_name, std::string const &description, std::string const &logic_class="")
virtual ~VerilogCodeTemplateGenerator ()
virtual std::string generate () const

Protected Member Functions

virtual std::string generate_header () const
virtual std::string generate_common () const
virtual std::string generate_port_list () const
virtual std::string generate_port_definition () const
virtual std::string generate_module (std::string const &entity_name, std::string const &port_description="") const
virtual std::string generate_impl (std::string const &logic_class="") const
virtual std::string generate_identifier (std::string const &name, std::string const &prefix="") const
 Generate a Verilog complient identifier from a string.

Detailed Description

A code template generator for Verilog.

Definition at line 39 of file VerilogCodeTemplateGenerator.h.


Member Typedef Documentation

typedef std::map<std::string, std::string> degate::VerilogCodeTemplateGenerator::port_map_type

Definition at line 50 of file VerilogCodeTemplateGenerator.h.


Constructor & Destructor Documentation

VerilogCodeTemplateGenerator::VerilogCodeTemplateGenerator ( std::string const &  entity_name,
std::string const &  description,
std::string const &  logic_class = "" 
)

Definition at line 38 of file VerilogCodeTemplateGenerator.cc.

                                                            {
}

Member Function Documentation

std::string VerilogCodeTemplateGenerator::generate ( ) const [virtual]
std::string VerilogCodeTemplateGenerator::generate_common ( ) const [protected, virtual]

Reimplemented in degate::VerilogModuleGenerator.

Definition at line 52 of file VerilogCodeTemplateGenerator.cc.

Referenced by generate().

                                                              {
  return "";
}

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_header ( ) const [protected, virtual]

Reimplemented in degate::VerilogTBCodeTemplateGenerator.

Definition at line 56 of file VerilogCodeTemplateGenerator.cc.

References degate::CodeTemplateGenerator::entity_name.

Referenced by generate().

                                                              {
  boost::format f("/** \n"
                  " * This is a Verilog implementation for a gate of type %1%.\n"
                  " */\n\n"
                  "// Please customize this code template according to your needs.\n"
                  "\n\n");
  f % entity_name;
  return f.str();
}

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_identifier ( std::string const &  name,
std::string const &  prefix = "" 
) const [protected, virtual]

Generate a Verilog complient identifier from a string.

Verilog identifier:

  • Must begin with alphabetic characters (a-z or A-Z)
  • Can contain alphanumeric (a-z, A-Z, 0-9) or underscore (_) characters
  • Can be up to 1024 characters long
  • Cannot contain white space
  • are not case sensitive.

Implements degate::CodeTemplateGenerator.

Definition at line 378 of file VerilogCodeTemplateGenerator.cc.

Referenced by degate::VerilogModuleGenerator::generate_impl(), generate_impl(), degate::VerilogTBCodeTemplateGenerator::generate_module(), generate_module(), generate_port_definition(), and generate_port_list().

                                                                                             {
  std::string identifier = prefix;

  bool first_char = prefix == "" ? true : false;
  BOOST_FOREACH(char c, name) {
    if(c == '/' || c == '!' || c == '~') identifier.append("not");
    else if(first_char && !isalpha(c)) {
      identifier.push_back('_');
      identifier.push_back(c);
    }
    else if(isalnum(c)) identifier.push_back(c);
    else identifier.push_back('_');

    first_char = false;
  }
  return identifier;
}

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_impl ( std::string const &  logic_class = "") const [protected, virtual]

Reimplemented in degate::VerilogModuleGenerator.

Definition at line 114 of file VerilogCodeTemplateGenerator.cc.

References degate::CodeTemplateGenerator::CLOCK, degate::CodeTemplateGenerator::D, degate::CodeTemplateGenerator::ENABLE, generate_identifier(), degate::CodeTemplateGenerator::get_first_port_name_not_in(), degate::CodeTemplateGenerator::get_inports(), degate::CodeTemplateGenerator::get_outports(), degate::CodeTemplateGenerator::get_port_name_by_type(), degate::CodeTemplateGenerator::NOT_Q, degate::CodeTemplateGenerator::Q, and degate::CodeTemplateGenerator::RESET.

Referenced by generate().

                                                                                        {

  std::vector<std::string> in = get_inports();
  std::vector<std::string> out = get_outports();

  if(in.size() == 0 || out.size() == 0) 
    throw DegateRuntimeException("The standard cell has either no input port or no ouput port.");

  std::string clock_name = get_port_name_by_type(CLOCK);
  if(clock_name.empty()) clock_name = "clock";
  std::string reset_name = get_port_name_by_type(RESET);
  if(reset_name.empty()) reset_name = "reset";
  std::string enable_name = get_port_name_by_type(ENABLE);
  if(reset_name.empty()) reset_name = "enable";

  if(logic_class == "inverter" &&
     in.size() == 1 && out.size() == 1) {

    boost::format f("  assign %1% = ~%2%;");
    f % generate_identifier(out[0]) % generate_identifier(in[0]);
    return f.str();
  }
  else if(logic_class == "tristate-inverter" ||
          logic_class == "tristate-inverter-lo-actiSve" ||
          logic_class == "tristate-inverter-hi-active") {

    bool low_active = logic_class == "tristate-inverter-lo-active";

    boost::format f("  tri %1%; // ???\n\n"
                    "  assign %2% = %3%%4% ? ~%5% : 1'bz;");
    f % generate_identifier(out[0]) 
      % generate_identifier(out[0])
      % (low_active ? "~" : "")
      % generate_identifier(enable_name)
      % generate_identifier(get_first_port_name_not_in(in, enable_name));
    return f.str();
  }
  else if((logic_class == "xor" ||
           logic_class == "or" ||
           logic_class == "and" ||
           logic_class == "nor" ||
           logic_class == "nand" ||
           logic_class == "xnor") &&
          in.size() >= 2 && out.size() == 1) {

    std::string inner_op, outer_op = "~";

    if(logic_class == "nand") inner_op = "&";
    else if(logic_class == "nor") inner_op = "|";
    else if(logic_class == "xnor") inner_op = "^";
    else {
      outer_op = "";
      if(logic_class == "and") inner_op = "&";
      else if(logic_class == "or") inner_op = "|";
      else if(logic_class == "xor") inner_op = "^";
    }

    boost::format f("  assign %1% = %2%%3%%4%%5%;"); 
    f % generate_identifier(out[0])
      % outer_op
      % (outer_op.empty() ? "" : "(")
      % boost::algorithm::join(generate_identifier<std::vector<std::string> >(in),
                               std::string(" ") + inner_op + std::string(" "))
      % (outer_op.empty() ? "" : ")");

    return f.str();
  }
  else if(logic_class == "buffer" && in.size() > 0 && out.size() > 0) {
    boost::format f("  assign %1% = %2%; // ???");
    f % generate_identifier(out[0]) % generate_identifier(in[0]);
    return f.str();

  }
  else if(logic_class == "buffer-tristate-hi-active" ||
          logic_class == "buffer-tristate-lo-active") {
    boost::format f("  tri %1%; // ???\n\n"
                    "  bufif%2%(%3%, %4%, %45);");
    f % generate_identifier(out[0])
      % (logic_class == "buffer-tristate-lo-active" ? "0" : "1")
      % generate_identifier(out[0])
      % generate_identifier(get_first_port_name_not_in(in, enable_name))
      % generate_identifier(enable_name);
    return f.str();
  }
  else if(logic_class == "latch-generic" ||
          logic_class == "latch-async-enable") {
    boost::format f("  reg %1%;\n\n"
                    "  always @(*)\n"
                    "    if (%2%) %3% = %4%;\n");
    f % generate_identifier(out[0])
      % generate_identifier(enable_name)
      % generate_identifier(out[0])
      % generate_identifier(get_first_port_name_not_in(in, enable_name));
    return f.str();

  }
  else if(logic_class == "latch-sync-enable") {
    return "  // stub not implemented, yet";
  }
  else if(logic_class == "flipflop") {
    boost::format f("  reg %1%;\n"
                    "\n"
                    "  always @(posedge %2%)\n"
                    "    %3% <= %4%;\n");
    f % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(CLOCK))
      % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(D));

    if(get_port_name_by_type(NOT_Q).empty())
      return f.str();
    else {
      boost::format f2("\n"
                       "  reg %1%;\n"
                       "\n"
                       "  always @*\n"
                       "    %2% <= ~%3%;\n");
      f2 % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(Q));

        return f.str() + f2.str();
    }
  }
  else if(logic_class == "flipflop-sync-rst") {
    boost::format f("  reg %1%;\n"
                    "\n"
                    "  always @(posedge %2%)\n"
                    "    if(%3%) // synchronous reset\n"
                    "      %4% <= 1'b0;\n"
                    "    else\n"
                    "      %5% <= %6%;\n");
    f % generate_identifier(get_port_name_by_type(Q)) // reg
      % generate_identifier(get_port_name_by_type(CLOCK)) // always

      % generate_identifier(get_port_name_by_type(RESET)) // if

      % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(D));


    if(get_port_name_by_type(NOT_Q).empty())
      return f.str();
    else {
      boost::format f2("\n"
                       "  reg %1%;\n"
                       "\n"
                       "  always @*\n"
                       "    %2% <= ~%3%;\n");
      f2 % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(Q));

        return f.str() + f2.str();
    }
    
  }
  else if(logic_class == "flipflop-async-rst") {
    boost::format f("  reg %1%;\n"
                    "\n"
                    "  always @(posedge %2% or posedge %3%)\n"
                    "    if(%4%) // asynchronous reset\n"
                    "      %5% <= 1'b0;\n"
                    "    else\n"
                    "      %6% <= %7%;\n");
    f % generate_identifier(get_port_name_by_type(Q)) // reg
      % generate_identifier(get_port_name_by_type(CLOCK)) // always
      % generate_identifier(get_port_name_by_type(RESET)) // always

      % generate_identifier(get_port_name_by_type(RESET)) // if

      % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(Q))
      % generate_identifier(get_port_name_by_type(D));

    if(get_port_name_by_type(NOT_Q).empty())
      return f.str();
    else {
      boost::format f2("\n"
                       "  reg %1%;\n"
                       "\n"
                       "  always @*\n"
                       "    %2% <= ~%3%;\n");
      f2 % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(NOT_Q))
        % generate_identifier(get_port_name_by_type(Q));

        return f.str() + f2.str();
    }

  }
  else if(logic_class == "generic-combinational-logic" ||
          logic_class == "ao" ||
          logic_class == "aoi" ||
          logic_class == "oa" ||
          logic_class == "oai") {
    
    std::string ret;
    BOOST_FOREACH(std::string const& oport,
                  generate_identifier<std::vector<std::string> >(get_outports())) {
      boost::format f("  assign %1% = ...;\n");
      f % oport;
      ret += f.str();
    }
                  
    return ret;
  }
  else if(logic_class == "half-adder") {
    return "  // assign {cout,sum} = a + b + cin;\n";
  }
  else if(logic_class == "full-adder") {
    return "  // stub not implemented, yet";
  }
  else if(logic_class == "mux") {

    boost::format f("  reg %1%;\n"
                    "\n"
                    "  always @*\n"
                    "    begin\n"
                    "      %2% = 1'b0; // default\n"
                    "      case({sel1, sel0}) // just an example\n"
                    "        2'b00 : %3% = a;\n"
                    "        2'b01 : %4% = b;\n"
                    "        2'b10 : %5% = c;\n"
                    "        2'b11 : %6% = d;\n"
                    "      endcase\n"
                    "    end\n");
    f % generate_identifier(out[0]) 
      % generate_identifier(out[0]) 
      % generate_identifier(out[0]) 
      % generate_identifier(out[0]) 
      % generate_identifier(out[0]) 
      % generate_identifier(out[0]);
    return f.str();
  }
  else if(logic_class == "demux") {
    boost::format f("  reg a, b, c, d;\n"
                    "\n"
                    "  always @*\n"
                    "    begin\n"
                    "      %1% = 1'b0; // default\n"
                    "      case({sel1, sel0}) // just an example\n"
                    "        2'b00 : a = %2%;\n"
                    "        2'b01 : b = %3%;\n"
                    "        2'b10 : c = %4%;\n"
                    "        2'b11 : d = %5%;\n"
                    "      endcase\n"
                    "    end\n");
    f % generate_identifier(in[0]) 
      % generate_identifier(in[0]) 
      % generate_identifier(in[0]) 
      % generate_identifier(in[0]) 
      % generate_identifier(in[0]);
    return f.str();
  }

  return
    "/*\n"
    " * Please implement behaviour.\n"
    " */\n";
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_module ( std::string const &  entity_name,
std::string const &  port_description = "" 
) const [protected, virtual]

Definition at line 66 of file VerilogCodeTemplateGenerator.cc.

References generate_identifier().

Referenced by generate().

                                                                                                   {

  boost::format f("module %1% (\n"
                  "%2%"
                  ");\n\n");
  f % generate_identifier(entity_name, "dg_")
    % port_description;
  return f.str();
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_port_definition ( ) const [protected, virtual]

Definition at line 88 of file VerilogCodeTemplateGenerator.cc.

References generate_identifier(), degate::CodeTemplateGenerator::get_inports(), and degate::CodeTemplateGenerator::get_outports().

Referenced by generate().

                                                                       {
  std::string ret;

  ret += "  // input ports\n";
  BOOST_FOREACH(std::string const& port_name, 
                generate_identifier<std::vector<std::string> >(get_inports())) {
    boost::format f("  input %1%;\n");
    f % port_name;    
    ret += f.str();
  }


  ret += "\n  // output ports\n";
  BOOST_FOREACH(std::string const& port_name, 
                generate_identifier<std::vector<std::string> >(get_outports())) {
    boost::format f("  output %1%;\n");
    f % port_name;    
    ret += f.str();
  }

  ret += "\n";

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

std::string VerilogCodeTemplateGenerator::generate_port_list ( ) const [protected, virtual]

Definition at line 77 of file VerilogCodeTemplateGenerator.cc.

References generate_identifier(), degate::CodeTemplateGenerator::get_inports(), and degate::CodeTemplateGenerator::get_outports().

Referenced by generate().

                                                                 {

  boost::format f("  %1%%2%\n"
                  "  %3%\n");
  f % boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_inports()), ", ")
    % (get_inports().size() > 0 ? ", " : "")
    % boost::algorithm::join(generate_identifier<std::vector<std::string> >(get_outports()), ", ");
  return f.str();
}

Here is the call graph for this function:

Here is the caller graph for this function:


The documentation for this class was generated from the following files: