Merge branch 'master' of git.libre-soc.org:soc
authorCole Poirier <colepoirier@gmail.com>
Mon, 24 Aug 2020 00:48:16 +0000 (17:48 -0700)
committerCole Poirier <colepoirier@gmail.com>
Mon, 24 Aug 2020 00:48:16 +0000 (17:48 -0700)
40 files changed:
libreriscv
src/soc/decoder/decode2execute1.py
src/soc/decoder/formal/proof_decoder2.py
src/soc/decoder/isa/caller.py
src/soc/decoder/power_decoder.py
src/soc/decoder/power_decoder2.py
src/soc/experiment/alu_fsm.py
src/soc/experiment/alu_hier.py
src/soc/experiment/compalu.py
src/soc/experiment/compldst_multi.py
src/soc/experiment/dcache.py
src/soc/experiment/test/test_compalu_multi.py
src/soc/experiment/test/test_l0_cache_buffer2.py
src/soc/fu/alu/alu_input_record.py
src/soc/fu/alu/formal/proof_input_stage.py
src/soc/fu/alu/main_stage.py
src/soc/fu/alu/test/test_pipe_caller.py
src/soc/fu/branch/formal/proof_input_stage.py
src/soc/fu/branch/main_stage.py
src/soc/fu/common_input_stage.py
src/soc/fu/compunits/compunits.py
src/soc/fu/cr/main_stage.py
src/soc/fu/div/test/test_pipe_caller.py
src/soc/fu/ldst/test/test_pipe_caller.py
src/soc/fu/logical/formal/proof_input_stage.py
src/soc/fu/logical/input_stage.py
src/soc/fu/logical/logical_input_record.py
src/soc/fu/logical/main_stage.py
src/soc/fu/logical/test/test_pipe_caller.py
src/soc/fu/mul/mul_input_record.py
src/soc/fu/shift_rot/input_stage.py
src/soc/fu/shift_rot/main_stage.py
src/soc/fu/shift_rot/maskgen.py
src/soc/fu/shift_rot/pipe_data.py
src/soc/litex/florent/sim.py
src/soc/simple/issuer.py
src/soc/simple/issuer_verilog.py
src/soc/simulator/gas.py
src/soc/simulator/program.py
src/soc/simulator/test_sim.py

index b444d0968ca397a04325b5a17b617807ba0bfedc..1b3c9590a8878194b8df77c10d184f26f2670ee8 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b444d0968ca397a04325b5a17b617807ba0bfedc
+Subproject commit 1b3c9590a8878194b8df77c10d184f26f2670ee8
index c5c2094527aa417945475d737ac7a93fd699f3e0..b3e6c691dfa743cd9f235453bebd9200d309a4a7 100644 (file)
@@ -42,7 +42,7 @@ class Decode2ToOperand(RecordObject):
         self.lk = Signal(reset_less=True)
         self.rc = Data(1, "rc")
         self.oe = Data(1, "oe")
-        self.invert_a = Signal(reset_less=True)
+        self.invert_in = Signal(reset_less=True)
         self.zero_a = Signal(reset_less=True)
         self.input_carry = Signal(CryIn, reset_less=True)
         self.output_carry = Signal(reset_less=True)
index 195044738bd693777a00b025e65e16d6d356eaf2..b7ac61f708ff3bfab70150e7a422b9366d710b8e 100644 (file)
@@ -182,7 +182,7 @@ class Driver(Elaboratable):
         pdecode2 = m.submodules.pdecode2
         dec = pdecode2.dec
         e = pdecode2.e
-        comb += Assert(e.invert_a == dec.op.inv_a)
+        comb += Assert(e.invert_in == dec.op.inv_a)
         comb += Assert(e.invert_out == dec.op.inv_out)
         comb += Assert(e.input_carry == dec.op.cry_in)
         comb += Assert(e.output_carry == dec.op.cry_out)
index 31ef345095018c5ed75b16f92eedf48e78300a8a..e3d349bb57f0a1638d987d018a08596b1b2f6c74 100644 (file)
@@ -406,7 +406,7 @@ class ISACaller:
         self.namespace['CA32'] = self.spr['XER'][XER_bits['CA32']].value
 
     def handle_carry_(self, inputs, outputs, already_done):
-        inv_a = yield self.dec2.e.do.invert_a
+        inv_a = yield self.dec2.e.do.invert_in
         if inv_a:
             inputs[0] = ~inputs[0]
 
@@ -442,7 +442,7 @@ class ISACaller:
             self.spr['XER'][XER_bits['CA32']] = cy32
 
     def handle_overflow(self, inputs, outputs, div_overflow):
-        inv_a = yield self.dec2.e.do.invert_a
+        inv_a = yield self.dec2.e.do.invert_in
         if inv_a:
             inputs[0] = ~inputs[0]
 
index 98912b0d4473605b0ff13a9624b45a5030f534a4..e4b87db1ca7debad7764c8318f222facd01f9914 100644 (file)
@@ -1,5 +1,10 @@
 """Cascading Power ISA Decoder
 
+License: LGPLv3
+
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
 This module uses CSV tables in a hierarchical/peer cascading fashion,
 to create a multi-level instruction decoder by recognising appropriate
 patterns.  The output is a wide, flattened (1-level) series of bitfields,
@@ -77,6 +82,7 @@ Top Level:
       ),
     ]
 
+
 """
 
 from collections import namedtuple
index 838cb121197db57bffe58e28ab02c50e5a1d57fb..51c3511f9dc93cde787029b4903e1358f57594da 100644 (file)
@@ -671,7 +671,7 @@ class PowerDecode2(Elaboratable):
 
         # decoded/selected instruction flags
         comb += do.data_len.eq(op.ldst_len)
-        comb += do.invert_a.eq(op.inv_a)
+        comb += do.invert_in.eq(op.inv_a)
         comb += do.invert_out.eq(op.inv_out)
         comb += do.input_carry.eq(op.cry_in)   # carry comes in
         comb += do.output_carry.eq(op.cry_out)  # carry goes out
index 9668535aedc8e507212906baf679dc37484b8e8d..596fc3d49764081c40bf075e8098919a6f5e1979 100644 (file)
@@ -206,7 +206,7 @@ class Shifter(Elaboratable):
 
 
 # Write a formatted GTKWave "save" file
-def write_gtkw(base_name, top_dut_name, loc):
+def write_gtkw_v1(base_name, top_dut_name, loc):
     # hierarchy path, to prepend to signal names
     dut = top_dut_name + "."
     # color styles
@@ -251,6 +251,150 @@ def write_gtkw(base_name, top_dut_name, loc):
             gtkw.trace(dut + "n_ready_i", color=style_input)
 
 
+def write_gtkw(gtkw_name, vcd_name, gtkw_dom, gtkw_style=None,
+               module=None, loc=None, color=None, base=None,
+               zoom=-22.9, marker=-1):
+    """ Write a GTKWave document according to the supplied style and DOM.
+
+    :param gtkw_name: name of the generated GTKWave document
+    :param vcd_name: name of the waveform file
+    :param gtkw_dom: DOM style description for the trace pane
+    :param gtkw_style: style for signals, classes and groups
+    :param module: default module
+    :param color: default trace color
+    :param base: default numerical base
+    :param loc: source code location to include as a comment
+    :param zoom: initial zoom level, in GTKWave format
+    :param marker: initial location of a marker
+
+    **gtkw_style format**
+
+    Syntax: ``{selector: {attribute: value, ...}, ...}``
+
+    "selector" can be a signal, class or group
+
+    Signal groups propagate most attributes to their children
+
+    Attribute choices:
+
+    * module: instance path, for prepending to the signal name
+    * color: trace color
+    * base: numerical base for value display
+    * display: alternate text to display in the signal pane
+    * comment: comment to display in the signal pane
+
+    **gtkw_dom format**
+
+    Syntax: ``[signal, (signal, class), (group, [children]), comment, ...]``
+
+    The DOM is a list of nodes.
+
+    Nodes are signals, signal groups or comments.
+
+    * signals are strings, or tuples: ``(signal name, class, class, ...)``
+    * signal groups are tuples: ``(group name, class, class, ..., [nodes])``
+    * comments are: ``{'comment': 'comment string'}``
+
+    In place of a class name, an inline class description can be used.
+    ``(signal, {attribute: value, ...}, ...)``
+    """
+    colors = {
+        'blue': GTKWColor.blue,
+        'cycle': GTKWColor.cycle,
+        'green': GTKWColor.green,
+        'indigo': GTKWColor.indigo,
+        'normal': GTKWColor.normal,
+        'orange': GTKWColor.orange,
+        'red': GTKWColor.red,
+        'violet': GTKWColor.violet,
+        'yellow': GTKWColor.yellow,
+    }
+
+    with open(gtkw_name, "wt") as gtkw_file:
+        gtkw = GTKWSave(gtkw_file)
+        if loc is not None:
+            gtkw.comment("Auto-generated by " + loc)
+        gtkw.dumpfile(vcd_name)
+        # set a reasonable zoom level
+        # also, move the marker to an interesting place
+        gtkw.zoom_markers(zoom, marker)
+
+        # create an empty style, if needed
+        if gtkw_style is None:
+            gtkw_style = dict()
+
+        # create an empty root selector, if needed
+        root_style = gtkw_style.get('', dict())
+
+        # apply styles to the root selector, if provided
+        if module is not None:
+            root_style['module'] = module
+        if color is not None:
+            root_style['color'] = color
+        if base is not None:
+            root_style['base'] = base
+        # base cannot be None, use 'hex' by default
+        if root_style.get('base') is None:
+            root_style['base'] = 'hex'
+
+        # recursively walk the DOM
+        def walk(dom, style):
+            for node in dom:
+                node_name = None
+                children = None
+                # copy the style from the parent
+                node_style = style.copy()
+                # node is a signal name string
+                if isinstance(node, str):
+                    node_name = node
+                    # apply style from node name, if specified
+                    if node_name in gtkw_style:
+                        node_style.update(gtkw_style[node_name])
+                # node is a tuple
+                # could be a signal or a group
+                elif isinstance(node, tuple):
+                    node_name = node[0]
+                    # collect styles from the selectors
+                    # order goes from the most specific to most generic
+                    # which means earlier selectors override later ones
+                    for selector in reversed(node):
+                        # update the node style from the selector
+                        if isinstance(selector, str):
+                            if selector in gtkw_style:
+                                node_style.update(gtkw_style[selector])
+                        # apply an inline style description
+                        elif isinstance(selector, dict):
+                            node_style.update(selector)
+                    # node is a group if it has a child list
+                    if isinstance(node[-1], list):
+                        children = node[-1]
+                # comment
+                elif isinstance(node, dict):
+                    if 'comment' in node:
+                        gtkw.blank(node['comment'])
+                # emit the group delimiters and walk over the child list
+                if children is not None:
+                    gtkw.begin_group(node_name)
+                    # pass on the group style to its children
+                    walk(children, node_style)
+                    gtkw.end_group(node_name)
+                # emit a trace, if the node is a signal
+                elif node_name is not None:
+                    signal_name = node_name
+                    # prepend module name to signal
+                    if 'module' in node_style:
+                        node_module = node_style['module']
+                        if node_module is not None:
+                            signal_name = node_module + '.' + signal_name
+                    node_color = colors.get(node_style.get('color'))
+                    node_base = node_style.get('base')
+                    display = node_style.get('display')
+                    gtkw.trace(signal_name, color=node_color,
+                               datafmt=node_base, alias=display)
+
+        walk(gtkw_dom, root_style)
+
+
 def test_shifter():
     m = Module()
     m.submodules.shf = dut = Shifter(8)
@@ -264,7 +408,65 @@ def test_shifter():
         f.write(il)
 
     # Write the GTKWave project file
-    write_gtkw("test_shifter", "top.shf", __file__)
+    write_gtkw_v1("test_shifter", "top.shf", __file__)
+
+    # Describe a GTKWave document
+
+    # Style for signals, classes and groups
+    gtkwave_style = {
+        # Root selector. Gives default attributes for every signal.
+        '': {'base': 'dec'},
+        # color the traces, according to class
+        # class names are not hardcoded, they are just strings
+        'in': {'color': 'orange'},
+        'out': {'color': 'yellow'},
+        # signals in the debug group have a common color and module path
+        'debug': {'module': 'top', 'color': 'red'},
+        # display a different string replacing the signal name
+        'test_case': {'display': 'test case'},
+    }
+
+    # DOM style description for the trace pane
+    gtkwave_desc = [
+        # simple signal, without a class
+        # even so, it inherits the top-level root attributes
+        'clk',
+        # comment
+        {'comment': 'Shifter Demonstration'},
+        # collapsible signal group
+        ('prev port', [
+            # attach a class style for each signal
+            ('op__sdir', 'in'),
+            ('p_data_i[7:0]', 'in'),
+            ('p_shift_i[7:0]', 'in'),
+            ('p_valid_i', 'in'),
+            ('p_ready_o', 'out'),
+        ]),
+        # Signals in a signal group inherit the group attributes.
+        # In this case, a different module path and color.
+        ('debug', [
+            {'comment': 'Some debug statements'},
+            # inline attributes, instead of a class name
+            ('zero', {'display': 'zero delay shift'}),
+            'interesting',
+            'test_case',
+            'msg',
+        ]),
+        ('internal', [
+            'fsm_state',
+            'count[3:0]',
+            'shift_reg[7:0]',
+        ]),
+        ('next port', [
+            ('n_data_o[7:0]', 'out'),
+            ('n_valid_o', 'out'),
+            ('n_ready_i', 'in'),
+        ]),
+    ]
+
+    write_gtkw("test_shifter_v2.gtkw", "test_shifter.vcd",
+               gtkwave_desc,  gtkwave_style,
+               module="top.shf", loc=__file__, marker=10500000)
 
     sim = Simulator(m)
     sim.add_clock(1e-6)
index 59bca26e358051b9579a9686833c8a9c93a1e393..9c8115ce69da2c035f0d674ac3768fceb415020d 100644 (file)
@@ -26,14 +26,14 @@ import operator
 
 class Adder(Elaboratable):
     def __init__(self, width):
-        self.invert_a = Signal()
+        self.invert_in = Signal()
         self.a = Signal(width)
         self.b = Signal(width)
         self.o = Signal(width, name="add_o")
 
     def elaborate(self, platform):
         m = Module()
-        with m.If(self.invert_a):
+        with m.If(self.invert_in):
             m.d.comb += self.o.eq((~self.a) + self.b)
         with m.Else():
             m.d.comb += self.o.eq(self.a + self.b)
@@ -206,7 +206,7 @@ class ALU(Elaboratable):
             ]
 
         # pass invert (and carry later)
-        m.d.comb += add.invert_a.eq(self.op.invert_a)
+        m.d.comb += add.invert_in.eq(self.op.invert_in)
 
         go_now = Signal(reset_less=True)  # testing no-delay ALU
 
@@ -390,7 +390,7 @@ def run_op(dut, a, b, op, inv_a=0):
     yield dut.a.eq(a)
     yield dut.b.eq(b)
     yield dut.op.insn_type.eq(op)
-    yield dut.op.invert_a.eq(inv_a)
+    yield dut.op.invert_in.eq(inv_a)
     yield dut.n.ready_i.eq(0)
     yield dut.p.valid_i.eq(1)
     yield dut.n.ready_i.eq(1)
@@ -404,7 +404,7 @@ def run_op(dut, a, b, op, inv_a=0):
     yield dut.a.eq(0)
     yield dut.b.eq(0)
     yield dut.op.insn_type.eq(0)
-    yield dut.op.invert_a.eq(0)
+    yield dut.op.invert_in.eq(0)
 
     # wait for the ALU to present the output data
     while not (yield dut.n.valid_o):
@@ -462,7 +462,7 @@ def test_alu_parallel():
         yield dut.a.eq(a)
         yield dut.b.eq(b)
         yield dut.op.insn_type.eq(op)
-        yield dut.op.invert_a.eq(inv_a)
+        yield dut.op.invert_in.eq(inv_a)
         yield dut.p.valid_i.eq(1)
         yield
         # wait for ready_o to be asserted
@@ -475,7 +475,7 @@ def test_alu_parallel():
         yield dut.a.eq(0)
         yield dut.b.eq(0)
         yield dut.op.insn_type.eq(0)
-        yield dut.op.invert_a.eq(0)
+        yield dut.op.invert_in.eq(0)
 
     def receive():
         # signal readiness to receive data
index dcab911aa657e5f2fada58e6e207b85ef737c9f8..89d2da1a2c8c0210b0733d6a9c5b0f2ef634b92c 100644 (file)
@@ -175,7 +175,7 @@ def op_sim(dut, a, b, op, inv_a=0, imm=0, imm_ok=0):
     yield dut.src1_i.eq(a)
     yield dut.src2_i.eq(b)
     yield dut.oper_i.insn_type.eq(op)
-    yield dut.oper_i.invert_a.eq(inv_a)
+    yield dut.oper_i.invert_in.eq(inv_a)
     yield dut.oper_i.imm_data.imm.eq(imm)
     yield dut.oper_i.imm_data.imm_ok.eq(imm_ok)
     yield dut.issue_i.eq(1)
index 5109ad253e3a6d1f6fa75c66699bde286b223069..41739ed4551fb6c43124bfea7ae6bbcabbf5aa8c 100644 (file)
@@ -85,6 +85,7 @@ from nmigen.hdl.rec import Record, Layout
 
 from nmutil.latch import SRLatch, latchregister
 from nmutil.byterev import byte_reverse
+from nmutil.extend import exts
 
 from soc.experiment.compalu_multi import go_record, CompUnitRecord
 from soc.experiment.l0_cache import PortInterface
@@ -301,6 +302,17 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         p_st_go = Signal(reset_less=True)
         sync += p_st_go.eq(self.st.go_i)
 
+        # decode bits of operand (latched)
+        oper_r = CompLDSTOpSubset(name="oper_r")  # Dest register
+        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)  # ST
+        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)  # LD
+        op_is_update = oper_r.ldst_mode == LDSTMode.update           # UPDATE
+        op_is_cix = oper_r.ldst_mode == LDSTMode.cix           # cache-inhibit
+        comb += self.load_mem_o.eq(op_is_ld & self.go_ad_i)
+        comb += self.stwd_mem_o.eq(op_is_st & self.go_st_i)
+        comb += self.ld_o.eq(op_is_ld)
+        comb += self.st_o.eq(op_is_st)
+
         ##########################
         # FSM implemented through sequence of latches.  approximately this:
         # - opc_l       : opcode
@@ -340,7 +352,9 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
 
         # dest operand latch
         comb += wri_l.s.eq(issue_i)
-        sync += wri_l.r.eq(reset_w | Repl(self.done_o, self.n_dst))
+        sync += wri_l.r.eq(reset_w | Repl(self.done_o |
+                                          (self.pi.busy_o & op_is_update),
+                                          self.n_dst))
 
         # update-mode operand latch (EA written to reg 2)
         sync += upd_l.s.eq(reset_i)
@@ -359,7 +373,6 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += rst_l.r.eq(issue_i)
 
         # create a latch/register for the operand
-        oper_r = CompLDSTOpSubset(name="oper_r")  # Dest register
         with m.If(self.issue_i):
             sync += oper_r.eq(self.oper_i)
         with m.If(self.done_o):
@@ -398,16 +411,6 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += alu_o.eq(src1_or_z + src2_or_imm)  # actual EA
         m.d.sync += alu_ok.eq(alu_valid)             # keep ack in sync with EA
 
-        # decode bits of operand (latched)
-        comb += op_is_st.eq(oper_r.insn_type == MicrOp.OP_STORE)  # ST
-        comb += op_is_ld.eq(oper_r.insn_type == MicrOp.OP_LOAD)  # LD
-        op_is_update = oper_r.ldst_mode == LDSTMode.update           # UPDATE
-        op_is_cix = oper_r.ldst_mode == LDSTMode.cix           # cache-inhibit
-        comb += self.load_mem_o.eq(op_is_ld & self.go_ad_i)
-        comb += self.stwd_mem_o.eq(op_is_st & self.go_st_i)
-        comb += self.ld_o.eq(op_is_ld)
-        comb += self.st_o.eq(op_is_st)
-
         ############################
         # Control Signal calculation
 
@@ -490,13 +493,21 @@ class LDSTCompUnit(RegSpecAPI, Elaboratable):
         comb += addr_ok.eq(self.pi.addr_ok_o)  # no exc, address fine
 
         # byte-reverse on LD
+        revnorev = Signal(64, reset_less=True)
         with m.If(oper_r.byte_reverse):
             # byte-reverse the data based on ld/st width (turn it to LE)
             data_len = oper_r.data_len
             lddata_r = byte_reverse(m, 'lddata_r', pi.ld.data, data_len)
-            comb += ldd_o.eq(lddata_r)  # put reversed- data out
+            comb += revnorev.eq(lddata_r)  # put reversed- data out
         with m.Else():
-            comb += ldd_o.eq(pi.ld.data)  # put data out, straight (as BE)
+            comb += revnorev.eq(pi.ld.data)  # put data out, straight (as BE)
+
+        # then check sign-extend
+        with m.If(oper_r.sign_extend):
+            comb += ldd_o.eq(exts(revnorev, 32, 64))  # sign-extend
+        with m.Else():
+            comb += ldd_o.eq(revnorev)
+
         # ld - ld gets latched in via lod_l
         comb += ld_ok.eq(pi.ld.ok)  # ld.ok *closes* (freezes) ld data
 
index eab1b89c9019cbe372adda9a56c03f4b38dd2498..6d1356a00fac56ab799cd613cf3ed2a522159bd9 100644 (file)
@@ -1017,35 +1017,32 @@ class Dcache(Elaboratable):
 #     assert SET_SIZE_BITS <= TLB_LG_PGSZ
 #      report "Set indexed by virtual address" severity FAILURE;
         assert (LINE_SIZE % ROW_SIZE) == 0 "LINE_SIZE not " \
-         "multiple of ROW_SIZE -!- severity FAILURE"
+         "multiple of ROW_SIZE"
 
-        assert (LINE_SIZE % 2) == 0 "LINE_SIZE not power of" \
-         "2 -!- severity FAILURE"
+        assert (LINE_SIZE % 2) == 0 "LINE_SIZE not power of 2"
 
-        assert (NUM_LINES % 2) == 0 "NUM_LINES not power of" \
-         "2 -!- severity FAILURE"
+        assert (NUM_LINES % 2) == 0 "NUM_LINES not power of 2"
 
         assert (ROW_PER_LINE % 2) == 0 "ROW_PER_LINE not" \
-         "power of 2 -!- severity FAILURE"
+         "power of 2"
 
         assert ROW_BITS == (INDEX_BITS + ROW_LINE_BITS) \
-         "geometry bits don't add up -!- severity FAILURE"
+         "geometry bits don't add up"
 
         assert (LINE_OFF_BITS = ROW_OFF_BITS + ROW_LINEBITS) \
-         "geometry bits don't add up -!- severity FAILURE"
+         "geometry bits don't add up"
 
         assert REAL_ADDR_BITS == (TAG_BITS + INDEX_BITS \
-         + LINE_OFF_BITS) "geometry bits don't add up -!-" \
-         "severity FAILURE"
+         + LINE_OFF_BITS) "geometry bits don't add up"
 
         assert REAL_ADDR_BITS == (TAG_BITS + ROW_BITS + ROW_OFF_BITS) \
-         "geometry bits don't add up -!- severity FAILURE"
+         "geometry bits don't add up"
 
         assert 64 == wishbone_data_bits "Can't yet handle a" \
-         "wishbone width that isn't 64-bits -!- severity FAILURE"
+         "wishbone width that isn't 64-bits"
 
         assert SET_SIZE_BITS <= TLB_LG_PGSZ "Set indexed by" \
-         "virtual address -!- severity FAILURE"
+         "virtual address"
 
 #     -- Latch the request in r0.req as long as we're not stalling
 #     stage_0 : process(clk)
index 69269353ea5c056fb3d21d17ab4ebea88e86a5fd..97eb635f2f2c59d6a722c898b2bd6a3ac49a26a2 100644 (file)
@@ -77,7 +77,7 @@ def op_sim(dut, a, b, op, inv_a=0, imm=0, imm_ok=0, zero_a=0):
     yield dut.src_i[0].eq(a)
     yield dut.src_i[1].eq(b)
     yield dut.oper_i.insn_type.eq(op)
-    yield dut.oper_i.invert_a.eq(inv_a)
+    yield dut.oper_i.invert_in.eq(inv_a)
     yield dut.oper_i.imm_data.imm.eq(imm)
     yield dut.oper_i.imm_data.imm_ok.eq(imm_ok)
     yield dut.oper_i.zero_a.eq(zero_a)
@@ -285,7 +285,7 @@ class CompUnitParallelTest:
 
         # at the same time, present the operation
         yield self.dut.oper_i.insn_type.eq(self.op)
-        yield self.dut.oper_i.invert_a.eq(self.inv_a)
+        yield self.dut.oper_i.invert_in.eq(self.inv_a)
         yield self.dut.oper_i.imm_data.imm.eq(self.imm)
         yield self.dut.oper_i.imm_data.imm_ok.eq(self.imm_ok)
         yield self.dut.oper_i.zero_a.eq(self.zero_a)
@@ -310,7 +310,7 @@ class CompUnitParallelTest:
         # note: rdmaskn must be held, while busy_o is active
         # TODO: deactivate rdmaskn when the busy_o cycle ends
         yield self.dut.oper_i.insn_type.eq(0)
-        yield self.dut.oper_i.invert_a.eq(0)
+        yield self.dut.oper_i.invert_in.eq(0)
         yield self.dut.oper_i.imm_data.imm.eq(0)
         yield self.dut.oper_i.imm_data.imm_ok.eq(0)
         yield self.dut.oper_i.zero_a.eq(0)
index ba2a81703502b74e18943e4452c17ae6df0ca627..f23536e9be3e0474bb56c28073200c50682a526f 100644 (file)
@@ -35,7 +35,7 @@ class TestCachedMemoryPortInterface(PortInterfaceBase):
         #m.d.comb += self..eq(msbaddr)
 
     def set_wr_data(self, m, data, wen):
-        m.d.comb += self.ldst.st_data_i.eq(data)  # write st to mem
+        m.d.comb += self.ldst.st_data_i.data.eq(data)  # write st to mem
         m.d.comb += self.ldst.is_st_i.eq(wen)  # enable writes
         return Const(1, 1) #fixme -- write may be longer than one cycle
 
index 0b231cfda868e1a2565282bbd4bd4b4333aa6fbd..07fdb5f716e7beb3f9fa384060f846298c82b12b 100644 (file)
@@ -16,7 +16,7 @@ class CompALUOpSubset(CompOpSubsetBase):
                   ('imm_data', Layout((("imm", 64), ("imm_ok", 1)))),
                   ('rc', Layout((("rc", 1), ("rc_ok", 1)))), # Data
                   ('oe', Layout((("oe", 1), ("oe_ok", 1)))), # Data
-                  ('invert_a', 1),
+                  ('invert_in', 1),
                   ('zero_a', 1),
                   ('invert_out', 1),
                   ('write_cr0', 1),
index 0d664a750c872915ab421f58f6173088b48a0b79..afa39b1319b54c42134f55d7409efb46280c1642 100644 (file)
@@ -51,7 +51,7 @@ class Driver(Elaboratable):
             dut_sig = getattr(dut.o.ctx.op, name)
             comb += Assert(dut_sig == rec_sig)
 
-        with m.If(rec.invert_a):
+        with m.If(rec.invert_in):
             comb += Assert(dut.o.a == ~a)
         with m.Else():
             comb += Assert(dut.o.a == a)
index b2d2279cf80dec3670d70e5b65359c92a9794acf..16950629c743a301c62b7712420aeb436cce0e76 100644 (file)
@@ -3,6 +3,8 @@
 # as well as carry and overflow generation. This module
 # however should not gate the carry or overflow, that's up to the
 # output stage
+
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.extend import exts
index 2c730221f27e4ec203a1f7febe518a75ee3f7916..4e55dadcaa61ae42eb1ee79661bc0eb150cc8681 100644 (file)
@@ -99,6 +99,22 @@ class ALUTestCase(TestAccumulatorBase):
             initial_regs[2] = random.randint(0, (1 << 64)-1)
             self.add_case(Program(lst, bigendian), initial_regs)
 
+    def case_addis_nonzero_r0_regression(self):
+        lst = [f"addis 3, 0, 1"]
+        print(lst)
+        initial_regs = [0] * 32
+        initial_regs[0] = 5
+        self.add_case(Program(lst, bigendian), initial_regs)
+
+    def case_addis_nonzero_r0(self):
+        for i in range(10):
+            imm = random.randint(-(1 << 15), (1 << 15)-1)
+            lst = [f"addis 3, 0, {imm}"]
+            print(lst)
+            initial_regs = [0] * 32
+            initial_regs[0] = random.randint(0, (1 << 64)-1)
+            self.add_case(Program(lst, bigendian), initial_regs)
+
     def case_rand_imm(self):
         insns = ["addi", "addis", "subfic"]
         for i in range(10):
index 52409c4ea6617c59df754481381f6c23a28d0137..89346e21526ef1f3bd65f6fc9dcef660a5047a27 100644 (file)
@@ -51,7 +51,7 @@ class Driver(Elaboratable):
             dut_sig = getattr(dut.o.ctx.op, name)
             comb += Assert(dut_sig == rec_sig)
 
-        with m.If(rec.invert_a):
+        with m.If(rec.invert_in):
             comb += Assert(dut.o.a == ~a)
         with m.Else():
             comb += Assert(dut.o.a == a)
index 39631afdca281c1b280765281cbae5cb000b35b3..a8caa144b1905f2ba0cf51e79566d95894476527 100644 (file)
@@ -1,3 +1,7 @@
+# License: LGPLv3
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+
 """Branch Pipeline
 
 This stage is intended to do most of the work of executing branch
index 745be7726b032fa29b6d4cbbfe45c2140c90e0b7..238c8d57a9dec7907d497701597f01e419d90ebb 100644 (file)
@@ -19,8 +19,12 @@ class CommonInputStage(PipeModBase):
         # operand a to be as-is or inverted
         a = Signal.like(self.i.a)
 
-        if hasattr(op, "invert_a"):
-            with m.If(op.invert_a):
+        op_to_invert = 'ra'
+        if hasattr(self, "invert_op"):
+            op_to_invert = self.invert_op
+
+        if hasattr(op, "invert_in") and op_to_invert == 'ra':
+            with m.If(op.invert_in):
                 comb += a.eq(~self.i.a)
             with m.Else():
                 comb += a.eq(self.i.a)
@@ -29,6 +33,21 @@ class CommonInputStage(PipeModBase):
 
         comb += self.o.a.eq(a)
 
+        ##### operand B #####
+
+        # operand b to be as-is or inverted
+        b = Signal.like(self.i.b)
+
+        if hasattr(op, "invert_in") and op_to_invert == 'rb':
+            with m.If(op.invert_in):
+                comb += b.eq(~self.i.b)
+            with m.Else():
+                comb += b.eq(self.i.b)
+        else:
+            comb += b.eq(self.i.b)
+
+        comb += self.o.b.eq(b)
+
         ##### carry-in #####
 
         # either copy incoming carry or set to 1/0 as defined by op
index 9cf44a9924faafd76eb5649b3978e7f656a9785a..c5756fbae0daa46d97d3bdece800e1132c3af591 100644 (file)
@@ -73,6 +73,7 @@ from soc.fu.trap.pipe_data import TrapPipeSpec
 
 from soc.fu.div.pipeline import DivBasePipe
 from soc.fu.div.pipe_data import DivPipeSpecFSMDivCore
+from soc.fu.div.pipe_data import DivPipeSpecDivPipeCore
 
 from soc.fu.mul.pipeline import MulBasePipe
 from soc.fu.mul.pipe_data import MulPipeSpec
@@ -162,7 +163,8 @@ class DivFunctionUnit(FunctionUnitBaseSingle):
     fnunit = Function.DIV
 
     def __init__(self, idx):
-        super().__init__(DivPipeSpecFSMDivCore, DivBasePipe, idx)
+        #super().__init__(DivPipeSpecFSMDivCore, DivBasePipe, idx)
+        super().__init__(DivPipeSpecDivPipeCore, DivBasePipe, idx)
 
 
 class MulFunctionUnit(FunctionUnitBaseSingle):
index 27aa667042c2891d3f3de8e43290cdb2d332c53a..ac16f98972c6aab52511aa65b595070347bd04f5 100644 (file)
@@ -1,3 +1,7 @@
+# License: LGPLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 # This stage is intended to do Condition Register instructions (and ISEL)
 # and output, as well as carry and overflow generation.
 # NOTE: with the exception of mtcrf and mfcr, we really should be doing
index 34c54f372c1f8aadcac3017e6132c8a38d18498a..ccd3e1b686b6b9751c6d8b4187b1768599fe455f 100644 (file)
@@ -12,6 +12,26 @@ from soc.fu.div.test.helper import (log_rand, get_cu_inputs,
 
 class DivTestCases(TestAccumulatorBase):
 
+    # modulo
+    def case_modsd_regression(self):
+        lst = [f"modsd 17, 27, 0"]
+        initial_regs = [0] * 32
+        initial_regs[0] = 0xff
+        initial_regs[27] = 0x7fffffffffffffff
+        with Program(lst, bigendian) as prog:
+            self.add_case(prog, initial_regs)
+
+    def case_divduo_regression(self):
+        lst = [f"divduo. 11, 20, 6"]
+        initial_regs = [0] * 32
+        #gpr: 00ff00ff00ff0080 <- r6
+        #gpr: 000000000000007f <- r11
+        #gpr: 7f6e5d4c3b2a1908 <- r20
+        initial_regs[6] = 0x00ff00ff00ff0080
+        initial_regs[20] = 0x7f6e5d4c3b2a1908
+        with Program(lst, bigendian) as prog:
+            self.add_case(prog, initial_regs)
+
     def case_0_regression(self):
         for i in range(40):
             lst = ["divwo 3, 1, 2"]
@@ -110,6 +130,14 @@ class DivTestCases(TestAccumulatorBase):
         with Program(lst, bigendian) as prog:
             self.add_case(prog, initial_regs)
 
+    def case_11_regression(self):
+        lst = ["divwo. 3, 1, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0xffffffffffffffff
+        initial_regs[2] = 0xffffffffffffffff
+        with Program(lst, bigendian) as prog:
+            self.add_case(prog, initial_regs)
+
     def case_divw_by_zero_1(self):
         lst = ["divw. 3, 1, 2"]
         initial_regs = [0] * 32
index 31ddfc52c8e8669537ae366ac2c71834dfb65ea8..662b89d7b5bf40614a67ff423dcb21b77b566ef4 100644 (file)
@@ -167,3 +167,54 @@ class LDSTTestCase(TestAccumulatorBase):
         self.add_case(Program(lst, bigendian), initial_regs,
                              initial_mem=initial_mem)
 
+    def case_9_load_algebraic_1(self):
+        lst = ["lwax 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0xf000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
+    def case_9_load_algebraic_2(self):
+        lst = ["lwax 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0x7000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
+    def case_9_load_algebraic_3(self):
+        lst = ["lwaux 3, 4, 2"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[2] = 0x001c
+        initial_regs[4] = 0x0008
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0xf000000f0000ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
+    def case_9_load_algebraic_4(self):
+        lst = ["lwa 3, 4(4)"]
+        initial_regs = [0] * 32
+        initial_regs[1] = 0x5678
+        initial_regs[4] = 0x0020
+        initial_mem = {0x0000: (0x5432123412345678, 8),
+                       0x0008: (0xabcdef0187654321, 8),
+                       0x0020: (0xf000000f1234ffff, 8),
+                        }
+        self.add_case(Program(lst, bigendian), initial_regs,
+                             initial_mem=initial_mem)
+
index ab6e392e75061862365c331d05acecb84d7b5406..ed0c75119326f54c553b16c627e753f229a9e7ea 100644 (file)
@@ -51,7 +51,7 @@ class Driver(Elaboratable):
             dut_sig = getattr(dut.o.ctx.op, name)
             comb += Assert(dut_sig == rec_sig)
 
-        with m.If(rec.invert_a):
+        with m.If(rec.invert_in):
             comb += Assert(dut.o.a == ~a)
         with m.Else():
             comb += Assert(dut.o.a == a)
index df28187701f145abc75805172d3680f8ad941221..43f20c6e30c2f02e1c73e2eda7c3e4e65bd4276c 100644 (file)
@@ -9,6 +9,7 @@ from soc.fu.logical.pipe_data import LogicalInputData
 class LogicalInputStage(CommonInputStage):
     def __init__(self, pspec):
         super().__init__(pspec, "input")
+        self.invert_op = "rb" # inversion is on register b
 
     def ispec(self):
         return LogicalInputData(self.pspec)
@@ -17,11 +18,8 @@ class LogicalInputStage(CommonInputStage):
         return LogicalInputData(self.pspec)
 
     def elaborate(self, platform):
-        m = super().elaborate(platform) # covers A-invert, carry, excludes SO
+        m = super().elaborate(platform) # covers B-invert, carry, excludes SO
         comb = m.d.comb
         ctx = self.i.ctx
 
-        # operand b
-        comb += self.o.b.eq(self.i.b)
-
         return m
index 3e6780382c1f17a8790ec1ec49c46d36aa13a528..ad30488adcf7b55a0dcef959ac9355a005455316 100644 (file)
@@ -16,7 +16,7 @@ class CompLogicalOpSubset(CompOpSubsetBase):
                   ('imm_data', Layout((("imm", 64), ("imm_ok", 1)))),
                   ('rc', Layout((("rc", 1), ("rc_ok", 1)))),
                   ('oe', Layout((("oe", 1), ("oe_ok", 1)))),
-                  ('invert_a', 1),
+                  ('invert_in', 1),
                   ('zero_a', 1),
                   ('input_carry', CryIn),
                   ('invert_out', 1),
index ea102358332a6bf565d1b3bf195a5d2ad4b9fd2b..d6ae4a2f9e4dc0c33c95183c438190443fc69973 100644 (file)
@@ -5,6 +5,7 @@
 # This module however should not gate the carry or overflow, that's up
 # to the output stage
 
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
 from nmigen import (Module, Signal, Cat, Repl, Mux, Const, Array)
 from nmutil.pipemodbase import PipeModBase
 from nmutil.clz import CLZ
index 725cf306b11534c6dc2cc5d9a8daecc4ecedfc20..298f359c9b61fad4789a0f6c1a388971b9642ab9 100644 (file)
@@ -61,8 +61,18 @@ def set_alu_inputs(alu, dec2, sim):
 
 class LogicalTestCase(TestAccumulatorBase):
 
+    def case_complement(self):
+        insns = ["andc", "orc", "nand", "nor"]
+        for i in range(40):
+            choice = random.choice(insns)
+            lst = [f"{choice} 3, 1, 2"]
+            initial_regs = [0] * 32
+            initial_regs[1] = random.randint(0, (1 << 64)-1)
+            initial_regs[2] = random.randint(0, (1 << 64)-1)
+            self.add_case(Program(lst, bigendian), initial_regs)
+
     def case_rand(self):
-        insns = ["and", "or", "xor"]
+        insns = ["and", "or", "xor", "eqv"]
         for i in range(40):
             choice = random.choice(insns)
             lst = [f"{choice} 3, 1, 2"]
index b5334decae4768c63bae93c18672533bf6b3c9c2..1e667c05026e7473aa7b00d13b55a90ea2314b00 100644 (file)
@@ -17,9 +17,6 @@ class CompMULOpSubset(CompOpSubsetBase):
                   ('imm_data', Layout((("imm", 64), ("imm_ok", 1)))),
                   ('rc', Layout((("rc", 1), ("rc_ok", 1)))), # Data
                   ('oe', Layout((("oe", 1), ("oe_ok", 1)))), # Data
-                  ('invert_a', 1),
-                  ('zero_a', 1),
-                  ('invert_out', 1),
                   ('write_cr0', 1),
                   ('is_32bit', 1),
                   ('is_signed', 1),
index f195b40e82e3a1294662ea739f61b5651ade3f06..060555405752ca5e46a56d92e8391dbfa96c765c 100644 (file)
@@ -20,8 +20,7 @@ class ShiftRotInputStage(CommonInputStage):
         m = super().elaborate(platform) # handles A, carry and sticky overflow
         comb = m.d.comb
 
-        # operands ra and rb
-        comb += self.o.rb.eq(self.i.rb)
+        # operand rs
         comb += self.o.rs.eq(self.i.rs)
 
         return m
index 0ab4c460da359276273b452f355d3ebcfcbf2a38..c0459874e9e370717d2483f446aa952ddb6f48ae 100644 (file)
@@ -1,3 +1,7 @@
+# License: LGPLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 # This stage is intended to do most of the work of executing shift
 # instructions, as well as carry and overflow generation. This module
 # however should not gate the carry or overflow, that's up to the
index 89246e0b17fb3db9fd9c476e3c61af95b8d7b7a5..03072110e702a48d8573f321010d934c00e9b3b0 100644 (file)
@@ -1,5 +1,6 @@
 from nmigen import (Elaboratable, Signal, Module)
 import math
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
 
 class MaskGen(Elaboratable):
     """MaskGen - create a diff mask
index 280a757566bd58acd2fc50e97a170a0165dc528b..0477629670c0947d618a66c09b8595ca2aac1a92 100644 (file)
@@ -11,7 +11,8 @@ class ShiftRotInputData(IntegerData):
     def __init__(self, pspec):
         super().__init__(pspec, False)
         # convenience
-        self.a, self.rs = self.ra, self.rc
+        self.a, self.b, self.rs = self.ra, self.rb, self.rc
+
 
 
 class ShiftRotPipeSpec(CommonPipeSpec):
index e2d516bbc13b182dbc2814ce10ec214a9490111d..e4a1fbbf2446ea4c62694cdcdcc573dd69e1a137 100755 (executable)
@@ -14,6 +14,7 @@ from litex.soc.integration.soc import SoCRegion
 from litex.soc.integration.soc_core import SoCCore
 from litex.soc.integration.soc_sdram import SoCSDRAM
 from litex.soc.integration.builder import Builder
+from litex.soc.integration.common import get_mem_data
 
 from litedram import modules as litedram_modules
 from litedram.phy.model import SDRAMPHYModel
@@ -28,23 +29,43 @@ from microwatt import Microwatt
 
 class LibreSoCSim(SoCSDRAM):
     def __init__(self, cpu="libresoc", debug=False, with_sdram=True,
-            #sdram_module          = "AS4C16M16",
+            sdram_module          = "AS4C16M16",
             #sdram_data_width      = 16,
-            sdram_module          = "MT48LC16M16",
+            #sdram_module          = "MT48LC16M16",
             sdram_data_width      = 16,
             ):
         assert cpu in ["libresoc", "microwatt"]
         platform     = Platform()
         sys_clk_freq = int(100e6)
 
-        cpu_data_width = 32
-        #cpu_data_width = 64
+        #cpu_data_width = 32
+        cpu_data_width = 64
 
         if cpu_data_width == 32:
             variant = "standard32"
         else:
             variant = "standard"
 
+        #ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
+        #            "hello_world/hello_world.bin"
+        ram_fname = "/home/lkcl/src/libresoc/microwatt/" \
+                    "tests/1.bin"
+        #ram_fname = None
+
+        ram_init = []
+        if ram_fname:
+            #ram_init = get_mem_data({
+            #    ram_fname:       "0x00000000",
+            #    }, "little")
+            ram_init = get_mem_data(ram_fname, "little")
+
+            # remap the main RAM to reset-start-address
+            self.mem_map["main_ram"] = 0x00000000
+
+            # without sram nothing works, therefore move it to higher up
+            self.mem_map["sram"] = 0x90000000
+
+
         # SoCCore -------------------------------------------------------------
         SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
             cpu_type                 = "microwatt",
@@ -53,21 +74,23 @@ class LibreSoCSim(SoCSDRAM):
             #bus_data_width           = 64,
             cpu_variant              = variant,
             csr_data_width            = 32,
-            l2_cache_size             = 0,
+            l2_size             = 0,
             uart_name                = "sim",
             with_sdram               = with_sdram,
             sdram_module          = sdram_module,
             sdram_data_width      = sdram_data_width,
-            integrated_rom_size      = 0x10000,
+            integrated_rom_size      = 0 if ram_fname else 0x10000,
+            integrated_sram_size     = 0x40000,
+            #integrated_main_ram_init  = ram_init,
             integrated_main_ram_size = 0x00000000 if with_sdram \
                                         else 0x10000000 , # 256MB
-            ) 
+            )
         self.platform.name = "sim"
 
         # CRG -----------------------------------------------------------------
         self.submodules.crg = CRG(platform.request("sys_clk"))
 
-        ram_init = []
+        #ram_init = []
 
         # SDRAM ----------------------------------------------------
         if with_sdram:
@@ -122,6 +145,10 @@ class LibreSoCSim(SoCSDRAM):
         self.sync += uptime.eq(uptime + 1)
         #self.sync += If(uptime == 1000000000000, Finish())
 
+        # DMI FSM counter and FSM itself
+        dmicount = Signal(10)
+        dmirunning = Signal(1)
+        dmi_monitor = Signal(1)
         dmifsm = FSM()
         self.submodules += dmifsm
 
@@ -143,21 +170,37 @@ class LibreSoCSim(SoCSDRAM):
                  self.cpu.dmi_req.eq(1),    # DMI request
                  self.cpu.dmi_wr.eq(0),    # DMI read
                  If(self.cpu.dmi_ack,
+                    # acknowledge received: capture data.
                     (NextState("IDLE"),
                      NextValue(dbg_addr, dmi_addr),
                      NextValue(dbg_dout, self.cpu.dmi_dout),
                      NextValue(dbg_msg, 1),
-                    )
+                    ),
                  ),
                 ),
             )
         )
 
+        # DMI response received: reset the dmi request and check if
+        # in "monitor" mode
         dmifsm.act("IDLE",
-            (NextValue(dmi_req, 0),
-             NextValue(dmi_addr, 0),
+            If(dmi_monitor,
+                 NextState("FIRE_MONITOR"), # fire "monitor" on next cycle
+            ).Else(
+                 NextState("START"), # back to start on next cycle
+            ),
+            NextValue(dmi_req, 0),
+            NextValue(dmi_addr, 0),
+            NextValue(dmi_din, 0),
+            NextValue(dmi_wen, 0),
+        )
+
+        # "monitor" mode fires off a STAT request
+        dmifsm.act("FIRE_MONITOR",
+            (NextValue(dmi_req, 1),
+             NextValue(dmi_addr, 1), # DMI STAT address
              NextValue(dmi_din, 0),
-             NextValue(dmi_wen, 0),
+             NextValue(dmi_wen, 0), # read STAT
              NextState("START"), # back to start on next cycle
             )
         )
@@ -170,12 +213,20 @@ class LibreSoCSim(SoCSDRAM):
              If(dbg_addr == 0b10, # PC
                  pc.eq(dbg_dout),     # capture PC
              ),
-             If(dbg_addr == 0b11, # MSR
-                Display("    msr: %016x", dbg_dout),
-             ),
+             #If(dbg_addr == 0b11, # MSR
+             #   Display("    msr: %016x", dbg_dout),
+             #),
              If(dbg_addr == 0b101, # GPR
                 Display("    gpr: %016x", dbg_dout),
              ),
+            # also check if this is a "stat"
+            If(dbg_addr == 1, # requested a STAT
+                #Display("    stat: %x", dbg_dout),
+                If(dbg_dout & 2, # bit 2 of STAT is "stopped" mode
+                     dmirunning.eq(1), # continue running
+                     dmi_monitor.eq(0), # and stop monitor mode
+                ),
+            ),
              dbg_msg.eq(0)
             )
         )
@@ -189,11 +240,19 @@ class LibreSoCSim(SoCSDRAM):
             )
         )
 
+        self.sync += If(uptime == 4,
+             dmirunning.eq(1),
+        )
+
+        self.sync += If(dmirunning,
+             dmicount.eq(dmicount + 1),
+        )
+
         # loop every 1<<N cycles
         cyclewid = 9
 
         # get the PC
-        self.sync += If(uptime[0:cyclewid] == 4,
+        self.sync += If(dmicount == 4,
             (dmi_addr.eq(0b10), # NIA
              dmi_req.eq(1),
              dmi_wen.eq(0),
@@ -201,21 +260,23 @@ class LibreSoCSim(SoCSDRAM):
         )
 
         # kick off a "step"
-        self.sync += If(uptime[0:cyclewid] == 8,
+        self.sync += If(dmicount == 8,
             (dmi_addr.eq(0), # CTRL
              dmi_din.eq(1<<3), # STEP
              dmi_req.eq(1),
              dmi_wen.eq(1),
+             dmirunning.eq(0), # stop counter, need to fire "monitor"
+             dmi_monitor.eq(1), # start "monitor" instead
             )
         )
 
         # limit range of pc for debug reporting
-        #self.comb += active_dbg.eq((0x5108 <= pc) & (pc <= 0x5234))
+        #self.comb += active_dbg.eq((0x378c <= pc) & (pc <= 0x38d8))
         #self.comb += active_dbg.eq((0x0 < pc) & (pc < 0x58))
         self.comb += active_dbg.eq(1)
 
         # get the MSR
-        self.sync += If(active_dbg & (uptime[0:cyclewid] == 28),
+        self.sync += If(active_dbg & (dmicount == 12),
             (dmi_addr.eq(0b11), # MSR
              dmi_req.eq(1),
              dmi_wen.eq(0),
@@ -224,7 +285,7 @@ class LibreSoCSim(SoCSDRAM):
 
         # read all 32 GPRs
         for i in range(32):
-            self.sync += If(active_dbg & (uptime[0:cyclewid] == 30+(i*8)),
+            self.sync += If(active_dbg & (dmicount == 14+(i*8)),
                 (dmi_addr.eq(0b100), # GSPR addr
                  dmi_din.eq(i), # r1
                  dmi_req.eq(1),
@@ -232,18 +293,34 @@ class LibreSoCSim(SoCSDRAM):
                 )
             )
 
-            self.sync += If(active_dbg & (uptime[0:cyclewid] == 34+(i*8)),
+            self.sync += If(active_dbg & (dmicount == 18+(i*8)),
                 (dmi_addr.eq(0b101), # GSPR data
                  dmi_req.eq(1),
                  dmi_wen.eq(0),
                 )
             )
 
+        # monitor bbus read/write
+        self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
+            Display("    [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
+                #uptime,
+                0,
+                self.cpu.dbus.adr,
+                self.cpu.dbus.we,
+                self.cpu.dbus.sel,
+                self.cpu.dbus.dat_w,
+                self.cpu.dbus.dat_r
+            )
+        )
+
+        return
+
         # monitor ibus write
         self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
                         self.cpu.ibus.we,
             Display("    [%06x] iadr: %8x, s %01x w %016x",
-                uptime,
+                #uptime,
+                0,
                 self.cpu.ibus.adr,
                 self.cpu.ibus.sel,
                 self.cpu.ibus.dat_w,
@@ -253,25 +330,14 @@ class LibreSoCSim(SoCSDRAM):
         self.sync += If(active_dbg & self.cpu.ibus.stb & self.cpu.ibus.ack &
                         ~self.cpu.ibus.we,
             Display("    [%06x] iadr: %8x, s %01x r %016x",
-                uptime,
+                #uptime,
+                0,
                 self.cpu.ibus.adr,
                 self.cpu.ibus.sel,
                 self.cpu.ibus.dat_r
             )
         )
 
-        # monitor bbus read/write
-        self.sync += If(active_dbg & self.cpu.dbus.stb & self.cpu.dbus.ack,
-            Display("    [%06x] dadr: %8x, we %d s %01x w %016x r: %016x",
-                uptime,
-                self.cpu.dbus.adr,
-                self.cpu.dbus.we,
-                self.cpu.dbus.sel,
-                self.cpu.dbus.dat_w,
-                self.cpu.dbus.dat_r
-            )
-        )
-
 # Build -----------------------------------------------------------------------
 
 def main():
index ad4fd0a9112680cffbe08d3aecdf94dd8e928f81..cf516099aa40f11f6d6c1ea8fa1bb69749ea8e10 100644 (file)
@@ -156,9 +156,9 @@ class TestIssuer(Elaboratable):
 
         # connect up debug signals
         # TODO comb += core.icache_rst_i.eq(dbg.icache_rst_o)
-        comb += core.core_stopped_i.eq(dbg.core_stop_o)
         comb += dbg.terminate_i.eq(core.core_terminate_o)
         comb += dbg.state.pc.eq(pc)
+        #comb += dbg.state.pc.eq(cur_state.pc)
         comb += dbg.state.msr.eq(cur_state.msr)
 
         # temporaries
@@ -195,6 +195,9 @@ class TestIssuer(Elaboratable):
                     comb += self.state_r_msr.ren.eq(1<<StateRegs.MSR)
 
                     m.next = "INSN_READ" # move to "wait for bus" phase
+                with m.Else():
+                    comb += core.core_stopped_i.eq(1)
+                    comb += dbg.core_stopped_i.eq(1)
 
             # dummy pause to find out why simulation is not keeping up
             with m.State("INSN_READ"):
index f8f52d76949f92f473747f4cb8d8961327517677..46d36e99a581d462628083c288fb480e5c46365c 100644 (file)
@@ -26,7 +26,7 @@ if __name__ == '__main__':
                          # set to 32 for instruction-memory width=32
                          imem_reg_wid=64,
                          # set to 32 to make data wishbone bus 32-bit
-                         wb_data_wid=32,
+                         #wb_data_wid=32,
                          units=units)
     dut = TestIssuer(pspec)
 
index 571302bba870702ea76bdf56130254dd0edaecb4..5e36a14f5f3ba60528c70396edf3ba15c9af64a5 100644 (file)
@@ -1,3 +1,7 @@
+# License: LPGLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 import tempfile
 import subprocess
 import struct
index 1c254c929fd085366ee77545a67a1d8f8fd3e2ce..aeb33a23a170a893a0bcc4426a6bc2a774632790 100644 (file)
@@ -1,3 +1,7 @@
+# License: LGPLv3
+# Copyright (C) 2020 Michael Nolan <mtnolan2640@gmail.com>
+# Copyright (C) 2020 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+
 """POWER Program
 
 takes powerpc assembly instructions and turns them into LE/BE binary
index b6cb3097cf297cd996a075be555f1009778e281b..41c7e1d754338da55e7f02956bf0e5a80bfeb85e 100644 (file)
@@ -49,6 +49,24 @@ class GeneralTestCases(FHDLTestCase):
         super().__init__(name)
         self.test_name = name
 
+    def test_0_litex_bios_ctr_loop(self):
+        """
+        32a4:   ff ff 63 38     addi    r3,r3,-1
+        32a8:   20 00 63 78     clrldi  r3,r3,32
+        32ac:   01 00 23 39     addi    r9,r3,1
+        32b0:   a6 03 29 7d     mtctr   r9
+        32b4:   00 00 00 60     nop
+        32b8:   fc ff 00 42     bdnz    32b4 <cdelay+0x10>
+        32bc:   20 00 80 4e     blr
+
+        notes on converting pseudo-assembler to actual:
+
+        * bdnz target (equivalent to: bc 16,0,target)
+        * Clear left immediate clrldi ra,rs,n (n < 64) rldicl ra,rs,0,n
+        * CTR mtctr Rx mtspr 9,Rx
+        """
+        pass
+
     def test_0_litex_bios_cmp(self):
         """litex bios cmp test
         """
@@ -312,6 +330,23 @@ class GeneralTestCases(FHDLTestCase):
         with Program(lst, bigendian) as program:
             self.run_tst_program(program, [12])
 
+    #@unittest.skip("disable")
+    def test_31_addis(self):
+        """tests for zero not in register zero
+        """
+        lst = [  "rldicr  0, 0, 32, 31",
+                 "oris    0, 0, 32767",
+                 "ori     0, 0, 65535",
+                 "addis 1, 0, 1",
+                 "ori     1, 1, 515",
+                 "rldicr  1, 1, 32, 31",
+                 "oris    1, 1, 1029",
+                 "ori     1, 1, 1543",
+                 "addis   2, 0, -1",
+        ]
+        with Program(lst, bigendian) as program:
+            self.run_tst_program(program, [0, 1, 2])
+
     def run_tst_program(self, prog, initial_regs=None, initial_sprs=None,
                         initial_mem=None):
         initial_regs = [0] * 32