implementation for assignments working
authorStefan Biereigel <stefan.biereigel@cern.ch>
Thu, 23 May 2019 08:16:41 +0000 (10:16 +0200)
committerStefan Biereigel <stefan.biereigel@cern.ch>
Thu, 23 May 2019 11:57:27 +0000 (13:57 +0200)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc

index 5623541b2a68f9a6917912818c9cd2bd5f194d8a..9c360efb6a68e0e8536dcac5aa192796f3e65fd5 100644 (file)
@@ -51,6 +51,7 @@ namespace AST_INTERNAL {
        std::map<std::string, AstNode*> current_scope;
        const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
        RTLIL::SigSpec ignoreThisSignalsInInitial;
+    std::map<RTLIL::SigSpec, RTLIL::Cell*> wire_logic_map;
        AstNode *current_always, *current_top_block, *current_block, *current_block_child;
        AstModule *current_module;
        bool current_always_clocked;
@@ -940,6 +941,8 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
                log("--- END OF AST DUMP ---\n");
        }
 
+    wire_logic_map = std::map<RTLIL::SigSpec, RTLIL::Cell*>();
+
        if (!defer)
        {
                bool blackbox_module = flag_lib;
index 6c19dc7e61a4ade86f5c006608673030ee934e27..7b1744b2e69c3efd00dd4425a5fc91f5bd01fcb7 100644 (file)
@@ -327,6 +327,7 @@ namespace AST_INTERNAL
        extern std::map<std::string, AST::AstNode*> current_scope;
        extern const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr;
        extern RTLIL::SigSpec ignoreThisSignalsInInitial;
+    extern std::map<RTLIL::SigSpec, RTLIL::Cell*> wire_logic_map;
        extern AST::AstNode *current_always, *current_top_block, *current_block, *current_block_child;
        extern AST::AstModule *current_module;
        extern bool current_always_clocked;
index 379fed641a73c1657ccd233704f931c2692729d7..c60f8f5cc5a7ca1534075ea533a1cf9049a9c90a 100644 (file)
@@ -163,6 +163,42 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
        return wire;
 }
 
+// helper function for creating RTLIL code for wand/wor declarations
+static void wandwor2rtlil(AstNode *that, RTLIL::Wire *output_wire, bool gen_attributes = true)
+{
+    std::string type;
+
+    if (that->is_wand) {
+        type = "$reduce_and";
+    } else if (that->is_wor) {
+        type = "$reduce_or";
+    } else {
+        log_file_error(that->filename, that->linenum, "Unrecognized wired logic type.\n");
+    }
+
+       std::stringstream sstr;
+       sstr << type << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
+
+       RTLIL::Cell *cell = current_module->addCell(sstr.str(), type);
+       cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
+       
+       if (gen_attributes)
+               for (auto &attr : that->attributes) {
+                       if (attr.second->type != AST_CONSTANT)
+                               log_file_error(that->filename, that->linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
+                       cell->attributes[attr.first] = attr.second->asAttrConst();
+               }
+    
+       cell->parameters["\\A_SIGNED"] = RTLIL::Const(0);
+       cell->parameters["\\A_WIDTH"] = RTLIL::Const(0);
+       cell->setPort("\\A", RTLIL::SigSpec());
+    
+       cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1);
+       cell->setPort("\\Y", output_wire);
+                
+    wire_logic_map[output_wire] = cell;
+}
+
 // helper class for converting AST always nodes to RTLIL processes
 struct AST_INTERNAL::ProcessGenerator
 {
@@ -919,6 +955,13 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                        log_file_error(filename, linenum, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
                                wire->attributes[attr.first] = attr.second->asAttrConst();
                        }
+
+            if (is_wand || is_wor) {
+                if (wire->width > 1)
+                    log_file_error(filename, linenum, "Multi-bit wand/wor not supported.\n");
+                wandwor2rtlil(this, wire);
+            }
+
                }
                break;
 
@@ -1450,23 +1493,45 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        // add entries to current_module->connections for assignments (outside of always blocks)
        case AST_ASSIGN:
                {
+            bool left_had_const = false;
                        RTLIL::SigSpec left = children[0]->genRTLIL();
                        RTLIL::SigSpec right = children[1]->genWidthRTLIL(left.size());
-                       if (left.has_const()) {
-                               RTLIL::SigSpec new_left, new_right;
-                               for (int i = 0; i < GetSize(left); i++)
-                                       if (left[i].wire) {
-                                               new_left.append(left[i]);
-                                               new_right.append(right[i]);
-                                       }
-                               log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
-                                               "    old assignment: %s = %s\n    new assignment: %s = %s.\n",
-                                               log_signal(left), log_signal(right),
-                                               log_signal(new_left), log_signal(new_right));
-                               left = new_left;
-                               right = new_right;
-                       }
+
+            RTLIL::SigSpec new_left, new_right;
+            for (int i = 0; i < GetSize(left); i++)
+                if (left[i].wire) {
+                    std::map<RTLIL::SigSpec, RTLIL::Cell*>::iterator iter = wire_logic_map.find(left[i].wire);
+                    if (iter == wire_logic_map.end())
+                    {
+                        new_left.append(left[i]);
+                    } else {
+                        RTLIL::Cell *reduce_cell = iter->second;
+                        RTLIL::SigSpec reduce_cell_in = reduce_cell->getPort("\\A");
+                        int reduce_width = reduce_cell->getParam("\\A_WIDTH").as_int();
+                        log_warning("%d\n", reduce_cell_in.size());
+
+                        RTLIL::Wire *new_reduce_input = current_module->addWire(
+                                stringf("%s_in%d", reduce_cell->name.c_str(), reduce_width));
+                        new_reduce_input->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
+                        reduce_cell_in.append(new_reduce_input);
+                           reduce_cell->setPort("\\A", reduce_cell_in);
+                        reduce_cell->fixup_parameters();
+                        new_left.append(new_reduce_input);
+                    }
+                    new_right.append(right[i]);
+                } else {
+                    left_had_const = true;
+                }
+
+            left = new_left;
+            right = new_right;
                        current_module->connect(RTLIL::SigSig(left, right));
+            
+            if (left_had_const)
+                log_file_warning(filename, linenum, "Ignoring assignment to constant bits:\n"
+                        "    old assignment: %s = %s\n    new assignment: %s = %s.\n",
+                        log_signal(left), log_signal(right),
+                        log_signal(new_left), log_signal(new_right));
                }
                break;