convert numbers to python format master
authorTobias Platen <tplaten@posteo.de>
Sat, 25 Jan 2020 14:03:20 +0000 (15:03 +0100)
committerTobias Platen <tplaten@posteo.de>
Sat, 25 Jan 2020 14:03:20 +0000 (15:03 +0100)
absyn.py
examples/always_ff.sv [new file with mode: 0644]
examples/test_assignment.py [deleted file]
examples/tlb.py [deleted file]
parse_sv.py

index 2931be8..386e5d3 100644 (file)
--- a/absyn.py
+++ b/absyn.py
@@ -57,6 +57,8 @@ class CondStatement:
 def makeBlock(x):
     if(type(x) == Assignment):
         return [x]
+    elif(type(x) == CondStatement):
+        return [x]
     else:
         return x.statements
 
@@ -69,6 +71,7 @@ class Absyn:
         self.ports = []
         self.wires = []
         self.comb = []
+        self.sync = []
 
     def open(self):
         if(self.outputfile is None):
@@ -133,7 +136,9 @@ class Absyn:
 
     def do_assign(self, a, stmts, indent):
         stmts.children.append(self.indent(indent))
-        stmts.children.append(Leaf(token.STRING, "m.d.comb += "))
+        stmts.children.append(Leaf(token.STRING, "m.d."))
+        stmts.children.append(Leaf(token.STRING, self.blocktype))
+        stmts.children.append(Leaf(token.STRING, " += "))
         if(self.isPort(a.left)):
             stmts.children.append(Leaf(token.STRING, "self."))
         stmts.children.append(Leaf(token.STRING, a.left))
@@ -196,12 +201,18 @@ class Absyn:
             stmts.children.append(Leaf(token.STRING, ")"))
             stmts.children.append(self.nl())
 
-        # refactor: assignments non cond
+        self.blocktype = "comb"
         for a in self.assign:
-            self.do_assign(a, stmts)
+            self.do_assign(a, stmts, 2)
 
         for c in self.comb:
-            print("comb", c)
+            if(type(c) == Assignment):
+                self.do_assign(c, stmts, 2)
+            else:
+                self.do_ifblock(c, stmts, 2)
+
+        self.blocktype = "sync"
+        for c in self.sync:
             if(type(c) == Assignment):
                 self.do_assign(c, stmts, 2)
             else:
@@ -258,6 +269,9 @@ class Absyn:
 
     # cond assigmments and other nested blocks
     def always_comb(self, p3, p1):
-        print("always_comb")
         slist = p3[6]
         self.comb += slist.statements
+
+    def always_ff(self, p3, p1):
+        slist = p3[1]
+        self.sync += slist.statements
diff --git a/examples/always_ff.sv b/examples/always_ff.sv
new file mode 100644 (file)
index 0000000..1b7ca86
--- /dev/null
@@ -0,0 +1,11 @@
+module always_comb_test(
+    input clk,
+    input a,
+    output b
+);
+
+always_ff @(posedge clk) begin
+  a <= b;
+end
+  
+endmodule
diff --git a/examples/test_assignment.py b/examples/test_assignment.py
deleted file mode 100644 (file)
index 3972ac4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-from nmigen.compat.sim import run_simulation
-
-import assignment
-
-def tbench(dut):
-    yield dut.i.eq(1)
-    yield
-    yield
-    yield
-    yield dut.i.eq(0)
-    yield
-    yield
-    yield
-
-
-def test_ass():
-    dut = assignment.assignment();
-    run_simulation(dut, tbench(dut), vcd_name="test.vcd")
-
-
-if __name__ == "__main__":
-    test_ass()
diff --git a/examples/tlb.py b/examples/tlb.py
deleted file mode 100644 (file)
index 5e08a9f..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-# this file has been generated by sv2nmigen
-
-from nmigen import Signal, Module, Const, Cat, Elaboratable
-
-
-
-class tlb(Elaboratable):
-
-    def __init__(self):
-        self.clk_i = Signal() # input
-        self.rst_ni = Signal() # input
-        self.flush_i = Signal() # input
-        self.lu_access_i = Signal() # input
-        self.lu_asid_i = Signal(ASID_WIDTH) # input
-        self.lu_vaddr_i = Signal(64) # input
-        self.lu_is_2M_o = Signal() # output
-        self.lu_is_1G_o = Signal() # output
-        self.lu_hit_o = Signal() # output
-    def elaborate(self, platform=None):
-        m = Module()
-        return m
-
-#// Copyright 2018 ETH Zurich and University of Bologna.
-#// Copyright and related rights are licensed under the Solderpad Hardware
-#// License, Version 0.51 (the "License"); you may not use this file except in
-#// compliance with the License.  You may obtain a copy of the License at
-#// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
-#// or agreed to in writing, software, hardware and materials distributed under
-#// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-#// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-#// specific language governing permissions and limitations under the License.
-#//
-#// Author: David Schaffenrath, TU Graz
-#// Author: Florian Zaruba, ETH Zurich
-#// Date: 21.4.2017
-#// Description: Translation Lookaside Buffer, SV39
-#//              fully set-associative
-#
-#//import ariane_pkg::*;
-#
-#module tlb #(
-#      parameter int TLB_ENTRIES = 4,
-#      parameter int ASID_WIDTH  = 1
-#  )(
-#    input  logic                    clk_i,    // Clock
-#    input  logic                    rst_ni,   // Asynchronous reset active low
-#    input  logic                    flush_i,  // Flush signal
-#    // Update TLB
-#    //input  tlb_update_t             update_i,
-#    // Lookup signals
-#    input  logic                    lu_access_i,
-#    input  logic [ASID_WIDTH-1:0]   lu_asid_i,
-#    input  logic [63:0]             lu_vaddr_i,
-#    //output riscv::pte_t             lu_content_o,
-#    output logic                    lu_is_2M_o,
-#    output logic                    lu_is_1G_o,
-#    output logic                    lu_hit_o
-#);
-#
-"""    #docstring_begin
-    // SV39 defines three levels of page tables
-    struct packed {
-      logic [ASID_WIDTH-1:0] asid;
-      logic [8:0]            vpn2;
-      logic [8:0]            vpn1;
-      logic [8:0]            vpn0;
-      logic                  is_2M;
-      logic                  is_1G;
-      logic                  valid;
-    } [TLB_ENTRIES-1:0] tags_q, tags_n;
-
-    riscv::pte_t [TLB_ENTRIES-1:0] content_q, content_n;
-    logic [8:0] vpn0, vpn1, vpn2;
-    logic [TLB_ENTRIES-1:0] lu_hit;     // to replacement logic
-    logic [TLB_ENTRIES-1:0] replace_en; // replace the following entry, set by replacement strategy
-    //-------------
-    // Translation
-    //-------------
-    always_comb begin : translation
-        vpn0 = lu_vaddr_i[20:12];
-        vpn1 = lu_vaddr_i[29:21];
-        vpn2 = lu_vaddr_i[38:30];
-
-        // default assignment
-        lu_hit       = '{default: 0};
-        lu_hit_o     = 1'b0;
-        lu_content_o = '{default: 0};
-        lu_is_1G_o   = 1'b0;
-        lu_is_2M_o   = 1'b0;
-
-        for (int unsigned i = 0; i < TLB_ENTRIES; i++) begin
-            // first level match, this may be a giga page, check the ASID flags as well
-            if (tags_q[i].valid && lu_asid_i == tags_q[i].asid && vpn2 == tags_q[i].vpn2) begin
-                // second level
-                if (tags_q[i].is_1G) begin
-                    lu_is_1G_o = 1'b1;
-                    lu_content_o = content_q[i];
-                    lu_hit_o   = 1'b1;
-                    lu_hit[i]  = 1'b1;
-                // not a giga page hit so check further
-                end else if (vpn1 == tags_q[i].vpn1) begin
-                    // this could be a 2 mega page hit or a 4 kB hit
-                    // output accordingly
-                    if (tags_q[i].is_2M || vpn0 == tags_q[i].vpn0) begin
-                        lu_is_2M_o   = tags_q[i].is_2M;
-                        lu_content_o = content_q[i];
-                        lu_hit_o     = 1'b1;
-                        lu_hit[i]    = 1'b1;
-                    end
-                end
-            end
-        end
-    end
-
-    // ------------------
-    // Update and Flush
-    // ------------------
-    always_comb begin : update_flush
-        tags_n    = tags_q;
-        content_n = content_q;
-
-        for (int unsigned i = 0; i < TLB_ENTRIES; i++) begin
-            if (flush_i) begin
-                // invalidate logic
-                if (lu_asid_i == 1'b0) // flush everything if ASID is 0
-                    tags_n[i].valid = 1'b0;
-                else if (lu_asid_i == tags_q[i].asid) // just flush entries from this ASID
-                    tags_n[i].valid = 1'b0;
-
-            // normal replacement
-            end else if (update_i.valid & replace_en[i]) begin
-                // update tag array
-                tags_n[i] = '{
-                    asid:  update_i.asid,
-                    vpn2:  update_i.vpn [26:18],
-                    vpn1:  update_i.vpn [17:9],
-                    vpn0:  update_i.vpn [8:0],
-                    is_1G: update_i.is_1G,
-                    is_2M: update_i.is_2M,
-                    valid: 1'b1
-                };
-                // and content as well
-                content_n[i] = update_i.content;
-            end
-        end
-    end
-
-    // -----------------------------------------------
-    // PLRU - Pseudo Least Recently Used Replacement
-    // -----------------------------------------------
-    logic[2*(TLB_ENTRIES-1)-1:0] plru_tree_q, plru_tree_n;
-    always_comb begin : plru_replacement
-        plru_tree_n = plru_tree_q;
-        // The PLRU-tree indexing:
-        // lvl0        0
-        //            / \
-        //           /   \
-        // lvl1     1     2
-        //         / \   / \
-        // lvl2   3   4 5   6
-        //       / \ /\/\  /\
-        //      ... ... ... ...
-        // Just predefine which nodes will be set/cleared
-        // E.g. for a TLB with 8 entries, the for-loop is semantically
-        // equivalent to the following pseudo-code:
-        // unique case (1'b1)
-        // lu_hit[7]: plru_tree_n[0, 2, 6] = {1, 1, 1};
-        // lu_hit[6]: plru_tree_n[0, 2, 6] = {1, 1, 0};
-        // lu_hit[5]: plru_tree_n[0, 2, 5] = {1, 0, 1};
-        // lu_hit[4]: plru_tree_n[0, 2, 5] = {1, 0, 0};
-        // lu_hit[3]: plru_tree_n[0, 1, 4] = {0, 1, 1};
-        // lu_hit[2]: plru_tree_n[0, 1, 4] = {0, 1, 0};
-        // lu_hit[1]: plru_tree_n[0, 1, 3] = {0, 0, 1};
-        // lu_hit[0]: plru_tree_n[0, 1, 3] = {0, 0, 0};
-        // default: begin /* No hit */ end
-        // endcase
-        for (int unsigned i = 0; i < TLB_ENTRIES; i++) begin
-            automatic int unsigned idx_base, shift, new_index;
-            // we got a hit so update the pointer as it was least recently used
-            if (lu_hit[i] & lu_access_i) begin
-                // Set the nodes to the values we would expect
-                for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl++) begin
-                  idx_base = $unsigned((2**lvl)-1);
-                  // lvl0 <=> MSB, lvl1 <=> MSB-1, ...
-                  shift = $clog2(TLB_ENTRIES) - lvl;
-                  // to circumvent the 32 bit integer arithmetic assignment
-                  new_index =  ~((i >> (shift-1)) & 32'b1);
-                  plru_tree_n[idx_base + (i >> shift)] = new_index[0];
-                end
-            end
-        end
-        // Decode tree to write enable signals
-        // Next for-loop basically creates the following logic for e.g. an 8 entry
-        // TLB (note: pseudo-code obviously):
-        // replace_en[7] = &plru_tree_q[ 6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,1}
-        // replace_en[6] = &plru_tree_q[~6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,0}
-        // replace_en[5] = &plru_tree_q[ 5,~2, 0]; //plru_tree_q[0,2,5]=={1,0,1}
-        // replace_en[4] = &plru_tree_q[~5,~2, 0]; //plru_tree_q[0,2,5]=={1,0,0}
-        // replace_en[3] = &plru_tree_q[ 4, 1,~0]; //plru_tree_q[0,1,4]=={0,1,1}
-        // replace_en[2] = &plru_tree_q[~4, 1,~0]; //plru_tree_q[0,1,4]=={0,1,0}
-        // replace_en[1] = &plru_tree_q[ 3,~1,~0]; //plru_tree_q[0,1,3]=={0,0,1}
-        // replace_en[0] = &plru_tree_q[~3,~1,~0]; //plru_tree_q[0,1,3]=={0,0,0}
-        // For each entry traverse the tree. If every tree-node matches,
-        // the corresponding bit of the entry's index, this is
-        // the next entry to replace.
-        for (int unsigned i = 0; i < TLB_ENTRIES; i += 1) begin
-            automatic logic en;
-            automatic int unsigned idx_base, shift, new_index;
-            en = 1'b1;
-            for (int unsigned lvl = 0; lvl < $clog2(TLB_ENTRIES); lvl++) begin
-                idx_base = $unsigned((2**lvl)-1);
-                // lvl0 <=> MSB, lvl1 <=> MSB-1, ...
-                shift = $clog2(TLB_ENTRIES) - lvl;
-
-                // en &= plru_tree_q[idx_base + (i>>shift)] == ((i >> (shift-1)) & 1'b1);
-                new_index =  (i >> (shift-1)) & 32'b1;
-                if (new_index[0]) begin
-                  en &= plru_tree_q[idx_base + (i>>shift)];
-                end else begin
-                  en &= ~plru_tree_q[idx_base + (i>>shift)];
-                end
-            end
-            replace_en[i] = en;
-        end
-    end
-
-    // sequential process
-    always_ff @(posedge clk_i or negedge rst_ni) begin
-        if(~rst_ni) begin
-            tags_q      <= '{default: 0};
-            content_q   <= '{default: 0};
-            plru_tree_q <= '{default: 0};
-        end else begin
-            tags_q      <= tags_n;
-            content_q   <= content_n;
-            plru_tree_q <= plru_tree_n;
-        end
-    end
-    //--------------
-    // Sanity checks
-    //--------------
-
-    //pragma translate_off
-    `ifndef VERILATOR
-
-    initial begin : p_assertions
-      assert ((TLB_ENTRIES % 2 == 0) && (TLB_ENTRIES > 1))
-        else begin $error("TLB size must be a multiple of 2 and greater than 1"); $stop(); end
-      assert (ASID_WIDTH >= 1)
-        else begin $error("ASID width must be at least 1"); $stop(); end
-    end
-
-    // Just for checking
-    function int countSetBits(logic[TLB_ENTRIES-1:0] vector);
-      automatic int count = 0;
-      foreach (vector[idx]) begin
-        count += vector[idx];
-      end
-      return count;
-    endfunction
-
-    assert property (@(posedge clk_i)(countSetBits(lu_hit) <= 1))
-      else begin $error("More then one hit in TLB!"); $stop(); end
-    assert property (@(posedge clk_i)(countSetBits(replace_en) <= 1))
-      else begin $error("More then one TLB entry selected for next replace!"); $stop(); end
-
-    `endif
-    //pragma translate_on
-"""
-#endmodule
-#
-#
index 6a153ff..9ca18f6 100644 (file)
@@ -2350,6 +2350,11 @@ def p_number_1(p):
     if(parse_debug):
         print('number_1', list(p))
 
+    p[1] = p[1].replace("'b", "0b")
+    p[1] = p[1].replace("'x", "0x")
+    num = Leaf(token.NUMBER, "%s" % (p[1]))
+    p[0] = num
+
 
     # { p[0] = p[1]; based_size = 0;}
 ()
@@ -2359,6 +2364,8 @@ def p_number_2(p):
     '''number : DEC_NUMBER '''
     if(parse_debug):
         print('number_2', list(p))
+    p[1] = p[1].replace("'b", "0b")
+    p[1] = p[1].replace("'x", "0x")
     num = Leaf(token.NUMBER, "%s" % (p[1]))
     p[0] = num
 
@@ -2371,7 +2378,11 @@ def p_number_3(p):
     '''number : DEC_NUMBER BASED_NUMBER '''
     if(parse_debug):
         print('number_3', list(p))
-    num = Leaf(token.NUMBER, "%s:%s" % (p[1], p[2]))
+
+    p[2] = p[2].replace("'b", "0b")
+    p[2] = p[2].replace("'x", "0x")
+
+    num = Leaf(token.NUMBER, "%s" % (p[2]))
     p[0] = num
 
 
@@ -6237,8 +6248,11 @@ def p_expression_46(p):
     if(parse_debug):
         print('expression_46', list(p))
 
-    p[0] = Node(syms.atom, [p[1], Leaf(token.STRING, ' ? '),
-                            p[4], Leaf(token.STRING, ' : '), p[6]])
+    try:
+        p[0] = Node(syms.atom, [p[1], Leaf(token.STRING, ' ? '),
+                                p[4], Leaf(token.STRING, ' : '), p[6]])
+    except:
+        p[0] = "error in PETernary"
 
 
     # { PETernary*tmp = new PETernary(p[1], p[4], p[6]);
@@ -7648,6 +7662,9 @@ def p_hierarchy_identifier_3(p):
     if(parse_debug):
         print('hierarchy_identifier_3', list(p))
 
+        p[0] = Node(syms.atom, [p[1], Leaf(
+            token.STRING, '['), p[3], Leaf(token.STRING, ']')])
+
 
     # { pform_name_t * tmp = p[1];
     #    name_component_t&tail = tmp->back();
@@ -9148,6 +9165,8 @@ def p_module_item_40(p):
     if(parse_debug):
         print('module_item_40', list(p))
 
+    absyn.always_ff(p[3], p[1])
+
 
     # { PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_FF, p[3], p[1]);
     #  FILE_NAME(tmp, @2);
@@ -12279,6 +12298,8 @@ def p_statement_item_30(p):
     if(parse_debug):
         print('statement_item_30', list(p))
 
+    p[0] = [p[1], p[2]]
+
 
     # { PEventStatement*tmp = p[1];
     #  if (tmp == 0) {
@@ -12365,6 +12386,8 @@ def p_statement_item_35(p):
     if(parse_debug):
         print('statement_item_35', list(p))
 
+    p[0] = absyn.assign3(p[1], p[2], p[3])
+
 
     # { PAssignNB*tmp = new PAssignNB(p[1],p[3]);
     #  FILE_NAME(tmp, @1);