Added module->design and cell->module, wire->module pointers
[yosys.git] / frontends / ast / ast.cc
index d9ad6d8ef7e6b5a84b56117f1580ea4faa00e534..46b717ce008504c898c0da145cc41ab91c813f95 100644 (file)
@@ -32,7 +32,9 @@
 
 #include <sstream>
 #include <stdarg.h>
-#include <assert.h>
+#include <math.h>
+
+YOSYS_NAMESPACE_BEGIN
 
 using namespace AST;
 using namespace AST_INTERNAL;
@@ -77,6 +79,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_ARGUMENT)
        X(AST_RANGE)
        X(AST_CONSTANT)
+       X(AST_REALVALUE)
        X(AST_CELLTYPE)
        X(AST_IDENTIFIER)
        X(AST_PREFIX)
@@ -127,6 +130,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_ASSIGN)
        X(AST_CELL)
        X(AST_PRIMITIVE)
+       X(AST_CELLARRAY)
        X(AST_ALWAYS)
        X(AST_INITIAL)
        X(AST_BLOCK)
@@ -137,6 +141,7 @@ std::string AST::type2str(AstNodeType type)
        X(AST_DEFAULT)
        X(AST_FOR)
        X(AST_WHILE)
+       X(AST_REPEAT)
        X(AST_GENVAR)
        X(AST_GENFOR)
        X(AST_GENIF)
@@ -178,10 +183,12 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
        is_signed = false;
        is_string = false;
        range_valid = false;
+       range_swapped = false;
        port_id = 0;
        range_left = -1;
        range_right = 0;
        integer = 0;
+       realvalue = 0;
        id2ast = NULL;
        basic_prep = false;
 
@@ -244,6 +251,12 @@ void AstNode::dumpAst(FILE *f, std::string indent)
 
        std::string type_name = type2str(type);
        fprintf(f, "%s%s <%s:%d>", indent.c_str(), type_name.c_str(), filename.c_str(), linenum);
+
+       if (id2ast)
+               fprintf(f, " [%p -> %p]", this, id2ast);
+       else
+               fprintf(f, " [%p]", this);
+
        if (!str.empty())
                fprintf(f, " str='%s'", str.c_str());
        if (!bits.empty()) {
@@ -266,9 +279,11 @@ void AstNode::dumpAst(FILE *f, std::string indent)
        if (port_id > 0)
                fprintf(f, " port=%d", port_id);
        if (range_valid || range_left != -1 || range_right != 0)
-               fprintf(f, " range=[%d:%d]%s", range_left, range_right, range_valid ? "" : "!");
+               fprintf(f, " %srange=[%d:%d]%s", range_swapped ? "swapped_" : "", range_left, range_right, range_valid ? "" : "!");
        if (integer != 0)
                fprintf(f, " int=%u", (int)integer);
+       if (realvalue != 0)
+               fprintf(f, " real=%e", realvalue);
        fprintf(f, "\n");
 
        for (auto &it : attributes) {
@@ -452,6 +467,10 @@ void AstNode::dumpVlog(FILE *f, std::string indent)
                        fprintf(f, "%zd'b %s", bits.size(), RTLIL::Const(bits).as_string().c_str());
                break;
 
+       case AST_REALVALUE:
+               fprintf(f, "%e", realvalue);
+               break;
+
        case AST_BLOCK:
                if (children.size() == 1) {
                        children[0]->dumpVlog(f, indent);
@@ -604,6 +623,8 @@ bool AstNode::operator==(const AstNode &other) const
                return false;
        if (range_valid != other.range_valid)
                return false;
+       if (range_swapped != other.range_swapped)
+               return false;
        if (port_id != other.port_id)
                return false;
        if (range_left != other.range_left)
@@ -747,10 +768,64 @@ bool AstNode::asBool()
        return false;
 }
 
+int AstNode::isConst()
+{
+       if (type == AST_CONSTANT)
+               return 1;
+       if (type == AST_REALVALUE)
+               return 2;
+       return 0;
+}
+
+double AstNode::asReal(bool is_signed)
+{
+       if (type == AST_CONSTANT) {
+               RTLIL::Const val(bits);
+
+               bool is_negative = is_signed && val.bits.back() == RTLIL::State::S1;
+               if (is_negative)
+                       val = const_neg(val, val, false, false, val.bits.size());
+
+               double v = 0;
+               for (size_t i = 0; i < val.bits.size(); i++)
+                       // IEEE Std 1800-2012 Par 6.12.2: Individual bits that are x or z in
+                       // the net or the variable shall be treated as zero upon conversion.
+                       if (val.bits.at(i) == RTLIL::State::S1)
+                               v += exp2(i);
+               if (is_negative)
+                       v *= -1;
+
+               return v;
+       }
+
+       if (type == AST_REALVALUE)
+               return realvalue;
+
+       log_abort();
+}
+
+RTLIL::Const AstNode::realAsConst(int width)
+{
+       double v = round(realvalue);
+       RTLIL::Const result;
+       if (!std::isfinite(v)) {
+               result.bits = std::vector<RTLIL::State>(width, RTLIL::State::Sx);
+       } else {
+               bool is_negative = v < 0;
+               if (is_negative)
+                       v *= -1;
+               for (int i = 0; i < width; i++, v /= 2)
+                       result.bits.push_back((fmod(floor(v), 2) != 0) ? RTLIL::State::S1 : RTLIL::State::S0);
+               if (is_negative)
+                       result = const_neg(result, result, false, false, result.bits.size());
+       }
+       return result;
+}
+
 // create a new AstModule from an AST_MODULE AST node
 static AstModule* process_module(AstNode *ast, bool defer)
 {
-       assert(ast->type == AST_MODULE);
+       log_assert(ast->type == AST_MODULE);
 
        if (defer)
                log("Storing AST representation for module `%s'.\n", ast->str.c_str());
@@ -855,13 +930,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
        flag_icells = icells;
        flag_autowire = autowire;
 
-       assert(current_ast->type == AST_DESIGN);
+       log_assert(current_ast->type == AST_DESIGN);
        for (auto it = current_ast->children.begin(); it != current_ast->children.end(); it++) {
                if (flag_icells && (*it)->str.substr(0, 2) == "\\$")
                        (*it)->str = (*it)->str.substr(1);
                if (defer)
                        (*it)->str = "$abstract" + (*it)->str;
-               if (design->modules.count((*it)->str)) {
+               if (design->has((*it)->str)) {
                        if (!ignore_redef)
                                log_error("Re-definition of module `%s' at %s:%d!\n",
                                                (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
@@ -869,7 +944,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
                                        (*it)->str.c_str(), (*it)->filename.c_str(), (*it)->linenum);
                        continue;
                }
-               design->modules[(*it)->str] =  process_module(*it, defer);
+               design->add(process_module(*it, defer));
        }
 }
 
@@ -966,10 +1041,10 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin
                modname = "$paramod" + stripped_name + para_info;
        }
 
-       if (design->modules.count(modname) == 0) {
+       if (!design->has(modname)) {
                new_ast->str = modname;
-               design->modules[modname] = process_module(new_ast, false);
-               design->modules[modname]->check();
+               design->add(process_module(new_ast, false));
+               design->module(modname)->check();
        } else {
                log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
        }
@@ -981,6 +1056,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, std::map<RTLIL::IdStrin
 RTLIL::Module *AstModule::clone() const
 {
        AstModule *new_mod = new AstModule;
+       new_mod->name = name;
        cloneInto(new_mod);
 
        new_mod->ast = ast->clone();
@@ -1013,3 +1089,5 @@ void AST::use_internal_line_num()
        get_line_num = &internal_get_line_num;
 }
 
+YOSYS_NAMESPACE_END
+